├── .nvmrc ├── .watchmanconfig ├── .eslintignore ├── example ├── .watchmanconfig ├── jest.config.js ├── .bundle │ └── config ├── ios │ ├── File.swift │ ├── ReactNativeMatrixSdkExample │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── AppDelegate.mm │ │ ├── PrivacyInfo.xcprivacy │ │ ├── Info.plist │ │ └── LaunchScreen.storyboard │ ├── ReactNativeMatrixSdkExample-Bridging-Header.h │ ├── ReactNativeMatrixSdkExample.xcworkspace │ │ └── contents.xcworkspacedata │ ├── .xcode.env │ ├── ReactNativeMatrixSdkExampleTests │ │ ├── Info.plist │ │ └── ReactNativeMatrixSdkExampleTests.m │ ├── Podfile │ └── ReactNativeMatrixSdkExample.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ └── ReactNativeMatrixSdkExample.xcscheme ├── app.json ├── android │ ├── app │ │ ├── debug.keystore │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ └── drawable │ │ │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── java │ │ │ │ │ └── unomed │ │ │ │ │ │ └── reactnativematrixsdk │ │ │ │ │ │ └── example │ │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ │ └── MainApplication.kt │ │ │ │ └── AndroidManifest.xml │ │ │ └── debug │ │ │ │ └── AndroidManifest.xml │ │ ├── proguard-rules.pro │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── build.gradle │ ├── gradle.properties │ ├── gradlew.bat │ └── gradlew ├── index.js ├── react-native.config.js ├── babel.config.js ├── Gemfile ├── metro.config.js ├── package.json ├── src │ └── App.tsx ├── Gemfile.lock └── README.md ├── .gitattributes ├── tsconfig.build.json ├── android ├── src │ └── main │ │ ├── AndroidManifestNew.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── unomed │ │ └── reactnativematrixsdk │ │ ├── ReactNativeMatrixSdkPackage.kt │ │ └── ReactNativeMatrixSdkModule.kt ├── proguard-rules.pro ├── gradle.properties ├── CMakeLists.txt ├── cpp-adapter.cpp └── build.gradle ├── babel.config.js ├── .eslintrc ├── react-native.config.js ├── lefthook.yml ├── .editorconfig ├── .yarnrc.yml ├── .github ├── workflows │ ├── install.yml │ ├── library.yml │ ├── lint.yml │ ├── build-release.yml │ ├── build-ios.yml │ └── build-android.yml └── actions │ ├── setup-js │ └── action.yml │ └── generate │ └── action.yml ├── src ├── NativeReactNativeMatrixSdk.ts ├── index.tsx └── generated │ ├── matrix_sdk_common.ts │ ├── matrix_sdk_ui-ffi.ts │ ├── matrix_sdk_base-ffi.ts │ ├── matrix_sdk_common-ffi.ts │ ├── matrix_sdk_crypto-ffi.ts │ ├── matrix_sdk-ffi.ts │ └── matrix_sdk_base.ts ├── ios ├── ReactNativeMatrixSdk.h └── ReactNativeMatrixSdk.mm ├── cpp ├── unomed-react-native-matrix-sdk.h ├── unomed-react-native-matrix-sdk.cpp └── generated │ ├── matrix_sdk_ui.hpp │ ├── matrix_sdk_base.hpp │ ├── matrix_sdk_common.hpp │ ├── matrix_sdk_crypto.hpp │ └── matrix_sdk.hpp ├── patches └── uniffi-bindgen-react-native+0.29.3-1.patch ├── tsconfig.json ├── ubrn.yaml ├── turbo.json ├── .gitignore ├── scripts ├── package-binaries.js ├── download-binaries.js └── sort-uniffi-calls.js ├── ReactNativeMatrixSdk.podspec ├── README.md ├── CONTRIBUTING.md ├── package.json └── matrix-rust-sdk.patch /.nvmrc: -------------------------------------------------------------------------------- 1 | v18 2 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | src/ 2 | -------------------------------------------------------------------------------- /example/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /example/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | }; 4 | -------------------------------------------------------------------------------- /example/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | # specific for windows script files 3 | *.bat text eol=crlf 4 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "exclude": ["example", "lib"] 4 | } 5 | -------------------------------------------------------------------------------- /example/ios/File.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // ReactNativeMatrixSdkExample 4 | // 5 | 6 | import Foundation 7 | -------------------------------------------------------------------------------- /example/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ReactNativeMatrixSdkExample", 3 | "displayName": "ReactNativeMatrixSdkExample" 4 | } 5 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifestNew.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /example/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/debug.keystore -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | ReactNativeMatrixSdkExample 3 | 4 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | ['module:react-native-builder-bob/babel-preset', { modules: 'commonjs' }], 4 | ], 5 | }; 6 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : RCTAppDelegate 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Generated by uniffi-bindgen-react-native 2 | -dontwarn java.awt.* 3 | -keep class com.sun.jna.* { *; } 4 | -keepclassmembers class * extends com.sun.jna.* { public *; } -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/unomed-dev/react-native-matrix-sdk/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import App from './src/App'; 3 | import { name as appName } from './app.json'; 4 | 5 | AppRegistry.registerComponent(appName, () => App); 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "parserOptions": { 7 | "ecmaVersion": 2018, 8 | "sourceType": "module" 9 | }, 10 | "plugins": ["prettier"] 11 | } 12 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | ReactNativeMatrixSdk_kotlinVersion=1.7.0 2 | ReactNativeMatrixSdk_minSdkVersion=21 3 | ReactNativeMatrixSdk_targetSdkVersion=31 4 | ReactNativeMatrixSdk_compileSdkVersion=31 5 | ReactNativeMatrixSdk_ndkversion=21.4.7075529 6 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | @autoreleasepool { 8 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('@react-native-community/cli-types').UserDependencyConfig} 3 | */ 4 | module.exports = { 5 | dependency: { 6 | platforms: { 7 | android: { 8 | cmakeListsPath: 'generated/jni/CMakeLists.txt', 9 | }, 10 | }, 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /lefthook.yml: -------------------------------------------------------------------------------- 1 | pre-commit: 2 | parallel: true 3 | commands: 4 | lint: 5 | glob: "*.{js,ts,jsx,tsx}" 6 | run: npx eslint {staged_files} 7 | types: 8 | glob: "*.{js,ts, jsx, tsx}" 9 | run: npx tsc 10 | commit-msg: 11 | parallel: true 12 | commands: 13 | commitlint: 14 | run: npx commitlint --edit 15 | -------------------------------------------------------------------------------- /example/react-native.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pkg = require('../package.json'); 3 | 4 | module.exports = { 5 | project: { 6 | ios: { 7 | automaticPodsInstallation: true, 8 | }, 9 | }, 10 | dependencies: { 11 | [pkg.name]: { 12 | root: path.join(__dirname, '..'), 13 | }, 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | indent_style = space 10 | indent_size = 2 11 | 12 | end_of_line = lf 13 | charset = utf-8 14 | trim_trailing_whitespace = true 15 | insert_final_newline = true 16 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | nmHoistingLimits: workspaces 3 | 4 | plugins: 5 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs 6 | spec: "@yarnpkg/plugin-interactive-tools" 7 | - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs 8 | spec: "@yarnpkg/plugin-workspace-tools" 9 | 10 | yarnPath: .yarn/releases/yarn-3.6.1.cjs 11 | -------------------------------------------------------------------------------- /example/babel.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { getConfig } = require('react-native-builder-bob/babel-config'); 3 | const pkg = require('../package.json'); 4 | 5 | const root = path.resolve(__dirname, '..'); 6 | 7 | module.exports = getConfig( 8 | { 9 | presets: ['module:@react-native/babel-preset'], 10 | }, 11 | { root, pkg } 12 | ); 13 | -------------------------------------------------------------------------------- /.github/workflows/install.yml: -------------------------------------------------------------------------------- 1 | name: NPM install 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | 8 | jobs: 9 | install: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Install 13 | run: | 14 | mkdir my-app 15 | cd my-app 16 | npm init -y 17 | npm install @unomed/react-native-matrix-sdk 18 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /src/NativeReactNativeMatrixSdk.ts: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | import type { TurboModule } from 'react-native'; 3 | import { TurboModuleRegistry } from 'react-native'; 4 | 5 | export interface Spec extends TurboModule { 6 | installRustCrate(): boolean; 7 | cleanupRustCrate(): boolean; 8 | } 9 | 10 | export default TurboModuleRegistry.getEnforcing('ReactNativeMatrixSdk'); -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } 2 | plugins { id("com.facebook.react.settings") } 3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } 4 | rootProject.name = 'unomed.reactnativematrixsdk.example' 5 | include ':app' 6 | includeBuild('../node_modules/@react-native/gradle-plugin') 7 | -------------------------------------------------------------------------------- /example/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | # Exclude problematic versions of cocoapods and activesupport that causes build failures. 7 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' 8 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' 9 | gem 'xcodeproj', '< 1.26.0' 10 | gem 'concurrent-ruby', '< 1.3.5' 11 | -------------------------------------------------------------------------------- /ios/ReactNativeMatrixSdk.h: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | #ifdef __cplusplus 3 | #import "unomed-react-native-matrix-sdk.h" 4 | #endif 5 | 6 | #ifdef RCT_NEW_ARCH_ENABLED 7 | #import "RNReactNativeMatrixSdkSpec.h" 8 | 9 | @interface ReactNativeMatrixSdk : NSObject 10 | #else 11 | #import 12 | 13 | @interface ReactNativeMatrixSdk : NSObject 14 | #endif 15 | 16 | @end -------------------------------------------------------------------------------- /.github/workflows/library.yml: -------------------------------------------------------------------------------- 1 | name: Library 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | workflow_dispatch: 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | 18 | - name: Setup JS 19 | uses: ./.github/actions/setup-js 20 | 21 | - name: Build package 22 | run: yarn prepare 23 | -------------------------------------------------------------------------------- /example/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | workflow_dispatch: 10 | 11 | jobs: 12 | lint: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v4 17 | 18 | - name: Setup JS 19 | uses: ./.github/actions/setup-js 20 | 21 | - name: Lint files 22 | run: yarn lint 23 | 24 | - name: Typecheck files 25 | run: yarn typecheck 26 | -------------------------------------------------------------------------------- /example/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /cpp/unomed-react-native-matrix-sdk.h: -------------------------------------------------------------------------------- 1 | #ifndef UNOMED_REACTNATIVEMATRIXSDK_H 2 | #define UNOMED_REACTNATIVEMATRIXSDK_H 3 | // Generated by uniffi-bindgen-react-native 4 | #include 5 | #include 6 | #include 7 | 8 | namespace unomed_reactnativematrixsdk { 9 | using namespace facebook; 10 | 11 | uint8_t installRustCrate(jsi::Runtime &runtime, std::shared_ptr callInvoker); 12 | uint8_t cleanupRustCrate(jsi::Runtime &runtime); 13 | } 14 | 15 | #endif /* UNOMED_REACTNATIVEMATRIXSDK_H */ -------------------------------------------------------------------------------- /example/metro.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { getDefaultConfig } = require('@react-native/metro-config'); 3 | const { getConfig } = require('react-native-builder-bob/metro-config'); 4 | const pkg = require('../package.json'); 5 | 6 | const root = path.resolve(__dirname, '..'); 7 | 8 | /** 9 | * Metro configuration 10 | * https://facebook.github.io/metro/docs/configuration 11 | * 12 | * @type {import('metro-config').MetroConfig} 13 | */ 14 | module.exports = getConfig(getDefaultConfig(__dirname), { 15 | root, 16 | pkg, 17 | project: __dirname, 18 | }); 19 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "35.0.0" 4 | minSdkVersion = 24 5 | compileSdkVersion = 35 6 | targetSdkVersion = 34 7 | ndkVersion = "26.1.10909125" 8 | kotlinVersion = "1.9.25" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | } 19 | } 20 | 21 | apply plugin: "com.facebook.react.rootproject" 22 | -------------------------------------------------------------------------------- /patches/uniffi-bindgen-react-native+0.29.3-1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/uniffi-bindgen-react-native/crates/ubrn_cli/src/commands/generate.rs b/node_modules/uniffi-bindgen-react-native/crates/ubrn_cli/src/commands/generate.rs 2 | index 1b13ea1..a5113cc 100644 3 | --- a/node_modules/uniffi-bindgen-react-native/crates/ubrn_cli/src/commands/generate.rs 4 | +++ b/node_modules/uniffi-bindgen-react-native/crates/ubrn_cli/src/commands/generate.rs 5 | @@ -98,6 +98,7 @@ pub(crate) struct GenerateAllArgs { 6 | lib_file: Utf8PathBuf, 7 | 8 | /// Whether to generate native bindings or not. 9 | + #[clap(long, default_value = "false")] 10 | native_bindings: bool, 11 | } 12 | 13 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /.github/actions/setup-js/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup JS 2 | description: Set up Node.js and install dependencies 3 | 4 | runs: 5 | using: composite 6 | steps: 7 | - name: Setup Node.js 8 | uses: actions/setup-node@v4 9 | with: 10 | node-version-file: .nvmrc 11 | 12 | - name: Cache dependencies 13 | id: yarn-cache 14 | uses: actions/cache@v4 15 | with: 16 | path: | 17 | **/node_modules 18 | .yarn/install-state.gz 19 | key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}-${{ hashFiles('**/package.json', '!node_modules/**') }} 20 | restore-keys: | 21 | ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }} 22 | ${{ runner.os }}-yarn- 23 | 24 | - name: Install dependencies 25 | if: steps.yarn-cache.outputs.cache-hit != 'true' 26 | run: yarn install --immutable 27 | shell: bash 28 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": ".", 4 | "paths": { 5 | "@unomed/react-native-matrix-sdk": ["./src/index"] 6 | }, 7 | "allowUnreachableCode": false, 8 | "allowUnusedLabels": false, 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "jsx": "react-jsx", 12 | "lib": ["ESNext"], 13 | "module": "ESNext", 14 | "moduleResolution": "Bundler", 15 | "noEmit": true, 16 | "noFallthroughCasesInSwitch": true, 17 | "noImplicitReturns": true, 18 | "noImplicitUseStrict": false, 19 | "noStrictGenericChecks": false, 20 | "noUncheckedIndexedAccess": true, 21 | "noUnusedLocals": false, 22 | "noUnusedParameters": false, 23 | "resolveJsonModule": true, 24 | "skipLibCheck": true, 25 | "strict": true, 26 | "target": "ESNext", 27 | "verbatimModuleSyntax": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ubrn.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | crate: 3 | repo: https://github.com/matrix-org/matrix-rust-sdk 4 | rev: 5ef3ecac8c63d2373d8e45a47807769e602ebd89 # matrix-sdk-base-0.14.1 5 | manifestPath: bindings/matrix-sdk-ffi/Cargo.toml 6 | android: 7 | cargoExtras: ['--features', 'rustls-tls'] 8 | directory: android 9 | native_bindings_dir: kotlin 10 | useSharedLibrary: true 11 | jniLibs: src/main/jniLibs 12 | targets: 13 | - arm64-v8a 14 | - armeabi-v7a 15 | ios: 16 | cargoExtras: ['--features', 'rustls-tls'] 17 | directory: ios 18 | native_bindings_dir: swift 19 | targets: 20 | - aarch64-apple-ios 21 | - aarch64-apple-ios-sim 22 | - x86_64-apple-ios 23 | xcodebuildExtras: [] 24 | frameworkName: build/RnMatrixRustSdk 25 | noOverwrite: 26 | - "android/build.gradle" 27 | turboModule: 28 | cpp: cpp 29 | ts: src 30 | bindings: 31 | cpp: cpp/generated 32 | ts: src/generated 33 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "pipeline": { 4 | "build:android": { 5 | "env": ["ORG_GRADLE_PROJECT_newArchEnabled"], 6 | "inputs": [ 7 | "package.json", 8 | "android", 9 | "!android/build", 10 | "src/*.ts", 11 | "src/*.tsx", 12 | "example/package.json", 13 | "example/android", 14 | "!example/android/.gradle", 15 | "!example/android/build", 16 | "!example/android/app/build" 17 | ], 18 | "outputs": [] 19 | }, 20 | "build:ios": { 21 | "env": ["RCT_NEW_ARCH_ENABLED"], 22 | "inputs": [ 23 | "package.json", 24 | "*.podspec", 25 | "ios", 26 | "src/*.ts", 27 | "src/*.tsx", 28 | "example/package.json", 29 | "example/ios", 30 | "!example/ios/build", 31 | "!example/ios/Pods" 32 | ], 33 | "outputs": [] 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample/AppDelegate.mm: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | 5 | @implementation AppDelegate 6 | 7 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 8 | { 9 | self.moduleName = @"ReactNativeMatrixSdkExample"; 10 | // You can add your custom initial props in the dictionary below. 11 | // They will be passed down to the ViewController used by React Native. 12 | self.initialProps = @{}; 13 | 14 | return [super application:application didFinishLaunchingWithOptions:launchOptions]; 15 | } 16 | 17 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 18 | { 19 | return [self bundleURL]; 20 | } 21 | 22 | - (NSURL *)bundleURL 23 | { 24 | #if DEBUG 25 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 26 | #else 27 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 28 | #endif 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /example/android/app/src/main/java/unomed/reactnativematrixsdk/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package unomed.reactnativematrixsdk.example 2 | 3 | import com.facebook.react.ReactActivity 4 | import com.facebook.react.ReactActivityDelegate 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate 7 | 8 | class MainActivity : ReactActivity() { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | override fun getMainComponentName(): String = "ReactNativeMatrixSdkExample" 15 | 16 | /** 17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 19 | */ 20 | override fun createReactActivityDelegate(): ReactActivityDelegate = 21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 22 | } 23 | -------------------------------------------------------------------------------- /cpp/unomed-react-native-matrix-sdk.cpp: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | #include "unomed-react-native-matrix-sdk.h" 3 | #include "generated/matrix_sdk.hpp" 4 | #include "generated/matrix_sdk_base.hpp" 5 | #include "generated/matrix_sdk_common.hpp" 6 | #include "generated/matrix_sdk_crypto.hpp" 7 | #include "generated/matrix_sdk_ffi.hpp" 8 | #include "generated/matrix_sdk_ui.hpp" 9 | 10 | namespace unomed_reactnativematrixsdk { 11 | using namespace facebook; 12 | 13 | uint8_t installRustCrate(jsi::Runtime &runtime, std::shared_ptr callInvoker) { 14 | NativeMatrixSdk::registerModule(runtime, callInvoker); 15 | NativeMatrixSdkBase::registerModule(runtime, callInvoker); 16 | NativeMatrixSdkCommon::registerModule(runtime, callInvoker); 17 | NativeMatrixSdkCrypto::registerModule(runtime, callInvoker); 18 | NativeMatrixSdkFfi::registerModule(runtime, callInvoker); 19 | NativeMatrixSdkUi::registerModule(runtime, callInvoker); 20 | return true; 21 | } 22 | 23 | uint8_t cleanupRustCrate(jsi::Runtime &runtime) { 24 | return false; 25 | } 26 | } -------------------------------------------------------------------------------- /.github/workflows/build-release.yml: -------------------------------------------------------------------------------- 1 | name: Build (Release) 2 | on: 3 | workflow_dispatch: 4 | 5 | jobs: 6 | android: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v4 12 | 13 | - name: Generate 14 | uses: ./.github/actions/generate 15 | with: 16 | platform: android 17 | release: true 18 | 19 | - name: Upload artifact 20 | uses: actions/upload-artifact@v4 21 | with: 22 | name: android-libs 23 | path: android/**/*.so 24 | if-no-files-found: error 25 | 26 | ios: 27 | runs-on: macos-14 28 | 29 | steps: 30 | - name: Checkout 31 | uses: actions/checkout@v4 32 | 33 | - name: Generate 34 | uses: ./.github/actions/generate 35 | with: 36 | platform: ios 37 | release: true 38 | 39 | - name: Upload artifact 40 | uses: actions/upload-artifact@v4 41 | with: 42 | name: xcframework 43 | path: build/*.xcframework 44 | if-no-files-found: error 45 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryUserDefaults 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | CA92.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategorySystemBootTime 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | 35F9.1 29 | 30 | 31 | 32 | NSPrivacyCollectedDataTypes 33 | 34 | NSPrivacyTracking 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | .DS_Store 3 | 4 | # XDE 5 | .expo/ 6 | 7 | # VSCode 8 | .vscode/ 9 | jsconfig.json 10 | 11 | # Xcode 12 | build/ 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | *.xccheckout 23 | *.moved-aside 24 | DerivedData 25 | *.hmap 26 | *.ipa 27 | *.xcuserstate 28 | project.xcworkspace 29 | .xcode.env.local 30 | 31 | # Android/IJ 32 | .classpath 33 | .cxx 34 | .gradle 35 | .idea 36 | .project 37 | .settings 38 | local.properties 39 | android.iml 40 | *.aar 41 | 42 | # Cocoapods 43 | example/ios/Pods 44 | 45 | # Ruby 46 | example/vendor/ 47 | 48 | # node.js 49 | node_modules/ 50 | npm-debug.log 51 | yarn-debug.log 52 | yarn-error.log 53 | 54 | # BUCK 55 | buck-out/ 56 | \.buckd/ 57 | android/app/libs 58 | android/keystores/debug.keystore 59 | 60 | # Yarn 61 | .yarn/* 62 | !.yarn/patches 63 | !.yarn/plugins 64 | !.yarn/releases 65 | !.yarn/sdks 66 | !.yarn/versions 67 | 68 | # Expo 69 | .expo/ 70 | 71 | # Turborepo 72 | .turbo/ 73 | 74 | # generated by bob 75 | lib/ 76 | 77 | # uniffi-bindgen-react-native 78 | rust_modules/ 79 | *.a 80 | *.so 81 | 82 | # React Native Codegen 83 | ios/generated 84 | android/generated 85 | binaries.tar.gz 86 | -------------------------------------------------------------------------------- /android/src/main/java/com/unomed/reactnativematrixsdk/ReactNativeMatrixSdkPackage.kt: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | package com.unomed.reactnativematrixsdk 3 | 4 | import com.facebook.react.TurboReactPackage 5 | import com.facebook.react.bridge.NativeModule 6 | import com.facebook.react.bridge.ReactApplicationContext 7 | import com.facebook.react.module.model.ReactModuleInfo 8 | import com.facebook.react.module.model.ReactModuleInfoProvider 9 | import java.util.HashMap 10 | 11 | class ReactNativeMatrixSdkPackage : TurboReactPackage() { 12 | override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? { 13 | return if (name == ReactNativeMatrixSdkModule.NAME) { 14 | ReactNativeMatrixSdkModule(reactContext) 15 | } else { 16 | null 17 | } 18 | } 19 | 20 | override fun getReactModuleInfoProvider(): ReactModuleInfoProvider { 21 | return ReactModuleInfoProvider { 22 | val moduleInfos: MutableMap = HashMap() 23 | moduleInfos[ReactNativeMatrixSdkModule.NAME] = ReactModuleInfo( 24 | ReactNativeMatrixSdkModule.NAME, 25 | ReactNativeMatrixSdkModule.NAME, 26 | false, // canOverrideExistingModule 27 | false, // needsEagerInit 28 | false, // isCxxModule 29 | true // isTurboModule 30 | ) 31 | moduleInfos 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@unomed/react-native-matrix-sdk-example", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "start": "react-native start", 9 | "build:android": "react-native build-android --extra-params \"--no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a\"", 10 | "build:ios": "react-native build-ios --scheme ReactNativeMatrixSdkExample --mode Debug --extra-params \"-sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO\"" 11 | }, 12 | "dependencies": { 13 | "react": "18.3.1", 14 | "react-native": "0.76.9" 15 | }, 16 | "devDependencies": { 17 | "@babel/core": "^7.25.2", 18 | "@babel/preset-env": "^7.25.3", 19 | "@babel/runtime": "^7.25.0", 20 | "@react-native-community/cli": "15.0.1", 21 | "@react-native-community/cli-platform-android": "15.0.1", 22 | "@react-native-community/cli-platform-ios": "15.0.1", 23 | "@react-native/babel-preset": "0.76.9", 24 | "@react-native/metro-config": "0.76.9", 25 | "@react-native/typescript-config": "0.76.9", 26 | "react-native-builder-bob": "^0.31.0" 27 | }, 28 | "engines": { 29 | "node": ">=18" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /scripts/package-binaries.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const tar = require('tar'); 6 | 7 | async function packageBinaries() { 8 | const projectDir = path.join(__dirname, '..'); 9 | const buildDir = path.join(projectDir, 'build'); 10 | const androidLibsDir = path.join(projectDir, 'android', 'src', 'main', 'jniLibs'); 11 | const outputFile = path.join(projectDir, 'binaries.tar.gz'); 12 | 13 | if (!fs.existsSync(path.join(buildDir, 'RnMatrixRustSdk.xcframework'))) { 14 | console.error('No iOS binaries found in build directory. Run yarn generate:release first.'); 15 | process.exit(1); 16 | } 17 | 18 | if (!fs.existsSync(androidLibsDir)) { 19 | console.error('No Android binaries found in android/src/main/jniLibs directory. Run yarn generate:release first.'); 20 | process.exit(1); 21 | } 22 | 23 | console.log('Packaging binaries...'); 24 | 25 | await tar.c({ 26 | gzip: true, 27 | file: outputFile, 28 | cwd: projectDir, 29 | }, [ 30 | 'build', 31 | 'android/src/main/jniLibs' 32 | ]); 33 | 34 | const stats = fs.statSync(outputFile); 35 | const sizeMB = (stats.size / 1024 / 1024).toFixed(2); 36 | 37 | console.log(`Binaries packaged successfully: ${outputFile} (${sizeMB} MB)`); 38 | } 39 | 40 | if (require.main === module) { 41 | packageBinaries().catch(console.error); 42 | } 43 | 44 | module.exports = { packageBinaries }; -------------------------------------------------------------------------------- /example/src/App.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | import { StyleSheet, View, Text, TextInput, Button } from 'react-native'; 4 | import { ClientBuilder } from '@unomed/react-native-matrix-sdk'; 5 | 6 | export default function App() { 7 | const [homeserver, setHomeserver] = React.useState("https://matrix.org"); 8 | const [status, setStatus] = React.useState(""); 9 | 10 | const updateHomeserverLoginDetails = React.useCallback(async () => { 11 | if (!homeserver.length) { 12 | setStatus(""); 13 | return; 14 | } 15 | 16 | try { 17 | const client = await (new ClientBuilder()).homeserverUrl(homeserver).build(); 18 | const loginDetails = await client.homeserverLoginDetails(); 19 | 20 | setStatus(`url: ${loginDetails.url()}\n` 21 | + `supportsOidcLogin: ${loginDetails.supportsOidcLogin()}\n` 22 | + `supportsPasswordLogin: ${loginDetails.supportsPasswordLogin()}`); 23 | } catch (error) { 24 | setStatus(`${error}`); 25 | } 26 | }, [homeserver]); 27 | 28 | return ( 29 | 30 | 31 | 32 | {status} 33 | 34 | ); 35 | } 36 | 37 | const styles = StyleSheet.create({ 38 | container: { 39 | flex: 1, 40 | alignItems: 'center', 41 | justifyContent: 'center', 42 | } 43 | }); 44 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | ENV['RCT_NEW_ARCH_ENABLED'] = '1' 2 | 3 | # Resolve react_native_pods.rb with node to allow for hoisting 4 | require Pod::Executable.execute_command('node', ['-p', 5 | 'require.resolve( 6 | "react-native/scripts/react_native_pods.rb", 7 | {paths: [process.argv[1]]}, 8 | )', __dir__]).strip 9 | 10 | platform :ios, min_ios_version_supported 11 | prepare_react_native_project! 12 | 13 | linkage = ENV['USE_FRAMEWORKS'] 14 | if linkage != nil 15 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 16 | use_frameworks! :linkage => linkage.to_sym 17 | end 18 | 19 | target 'ReactNativeMatrixSdkExample' do 20 | config = use_native_modules! 21 | 22 | use_react_native!( 23 | :path => config[:reactNativePath], 24 | # An absolute path to your application root. 25 | :app_path => "#{Pod::Config.instance.installation_root}/.." 26 | ) 27 | 28 | target 'ReactNativeMatrixSdkExampleTests' do 29 | inherit! :complete 30 | # Pods for testing 31 | end 32 | 33 | 34 | pre_install do |installer| 35 | system("cd ../../ && npx bob build --target codegen") 36 | end 37 | 38 | post_install do |installer| 39 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 40 | react_native_post_install( 41 | installer, 42 | config[:reactNativePath], 43 | :mac_catalyst_enabled => false, 44 | # :ccache_enabled => true 45 | ) 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /android/src/main/java/com/unomed/reactnativematrixsdk/ReactNativeMatrixSdkModule.kt: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | package com.unomed.reactnativematrixsdk 3 | 4 | import com.facebook.react.bridge.ReactApplicationContext 5 | import com.facebook.react.module.annotations.ReactModule 6 | import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder 7 | 8 | @ReactModule(name = ReactNativeMatrixSdkModule.NAME) 9 | class ReactNativeMatrixSdkModule(reactContext: ReactApplicationContext) : 10 | NativeReactNativeMatrixSdkSpec(reactContext) { 11 | 12 | override fun getName(): String { 13 | return NAME 14 | } 15 | 16 | // Two native methods implemented in cpp-adapter.cpp, and ultimately 17 | // unomed-react-native-matrix-sdk.cpp 18 | 19 | external fun nativeInstallRustCrate(runtimePointer: Long, callInvoker: CallInvokerHolder): Boolean 20 | external fun nativeCleanupRustCrate(runtimePointer: Long): Boolean 21 | 22 | override fun installRustCrate(): Boolean { 23 | val context = this.reactApplicationContext 24 | return nativeInstallRustCrate( 25 | context.javaScriptContextHolder!!.get(), 26 | context.jsCallInvokerHolder!! 27 | ) 28 | } 29 | 30 | override fun cleanupRustCrate(): Boolean { 31 | return nativeCleanupRustCrate( 32 | this.reactApplicationContext.javaScriptContextHolder!!.get() 33 | ) 34 | } 35 | 36 | companion object { 37 | const val NAME = "ReactNativeMatrixSdk" 38 | 39 | init { 40 | System.loadLibrary("unomed-react-native-matrix-sdk") 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ReactNativeMatrixSdkExample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | 30 | NSAllowsArbitraryLoads 31 | 32 | NSAllowsLocalNetworking 33 | 34 | 35 | NSLocationWhenInUseUsageDescription 36 | 37 | UILaunchStoryboardName 38 | LaunchScreen 39 | UIRequiredDeviceCapabilities 40 | 41 | arm64 42 | 43 | UISupportedInterfaceOrientations 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | UIViewControllerBasedStatusBarAppearance 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | 25 | # Use this property to specify which architecture you want to build. 26 | # You can also override it from the CLI using 27 | # ./gradlew -PreactNativeArchitectures=x86_64 28 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 29 | 30 | # Use this property to enable support to the new architecture. 31 | # This will allow you to use TurboModules and the Fabric render in 32 | # your application. You should enable this flag either if you want 33 | # to write custom TurboModules/Fabric components OR use libraries that 34 | # are providing them. 35 | newArchEnabled=true 36 | 37 | # Use this property to enable or disable the Hermes JS engine. 38 | # If set to false, you will be using JSC instead. 39 | hermesEnabled=true 40 | 41 | newArchEnabled=true -------------------------------------------------------------------------------- /example/android/app/src/main/java/unomed/reactnativematrixsdk/example/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package unomed.reactnativematrixsdk.example 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.react.soloader.OpenSourceMergedSoMapping 13 | import com.facebook.soloader.SoLoader 14 | 15 | class MainApplication : Application(), ReactApplication { 16 | 17 | override val reactNativeHost: ReactNativeHost = 18 | object : DefaultReactNativeHost(this) { 19 | override fun getPackages(): List = 20 | PackageList(this).packages.apply { 21 | // Packages that cannot be autolinked yet can be added manually here, for example: 22 | // add(MyReactNativePackage()) 23 | } 24 | 25 | override fun getJSMainModuleName(): String = "index" 26 | 27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 28 | 29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 31 | } 32 | 33 | override val reactHost: ReactHost 34 | get() = getDefaultReactHost(applicationContext, reactNativeHost) 35 | 36 | override fun onCreate() { 37 | super.onCreate() 38 | SoLoader.init(this, OpenSourceMergedSoMapping) 39 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 40 | // If you opted-in for the New Architecture, we load the native entry point for this app. 41 | load() 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ReactNativeMatrixSdk.podspec: -------------------------------------------------------------------------------- 1 | # Generated by uniffi-bindgen-react-native 2 | require "json" 3 | 4 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 5 | folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' 6 | 7 | Pod::Spec.new do |s| 8 | s.name = "ReactNativeMatrixSdk" 9 | s.version = package["version"] 10 | s.summary = package["description"] 11 | s.homepage = package["homepage"] 12 | s.license = package["license"] 13 | s.authors = package["author"] 14 | 15 | s.platforms = { :ios => min_ios_version_supported } 16 | s.source = { :git => "https://github.com/unomed-dev/react-native-matrix-sdk.git", :tag => "#{s.version}" } 17 | 18 | s.source_files = "ios/**/*.{h,m,mm,swift}", "ios/generated/**/*.{h,m,mm}", "cpp/**/*.{hpp,cpp,c,h}", "cpp/generated/**/*.{hpp,cpp,c,h}" 19 | s.vendored_frameworks = "build/RnMatrixRustSdk.xcframework" 20 | s.dependency "uniffi-bindgen-react-native", "0.29.3-1" 21 | 22 | # Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0. 23 | # See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79. 24 | if respond_to?(:install_modules_dependencies, true) 25 | install_modules_dependencies(s) 26 | else 27 | s.dependency "React-Core" 28 | 29 | # Don't install the dependencies when we run `pod install` in the old architecture. 30 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then 31 | s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" 32 | s.pod_target_xcconfig = { 33 | "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", 34 | "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", 35 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" 36 | } 37 | s.dependency "React-Codegen" 38 | s.dependency "RCT-Folly" 39 | s.dependency "RCTRequired" 40 | s.dependency "RCTTypeSafety" 41 | s.dependency "ReactCommon/turbomodule/core" 42 | end 43 | end 44 | end -------------------------------------------------------------------------------- /.github/workflows/build-ios.yml: -------------------------------------------------------------------------------- 1 | name: Build (iOS) 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | workflow_dispatch: 10 | 11 | jobs: 12 | build: 13 | runs-on: macos-14 14 | env: 15 | TURBO_CACHE_DIR: .turbo/ios 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | 21 | - name: Generate 22 | uses: ./.github/actions/generate 23 | with: 24 | platform: ios 25 | release: false 26 | 27 | - name: Cache turborepo for iOS 28 | uses: actions/cache@v4 29 | with: 30 | path: ${{ env.TURBO_CACHE_DIR }} 31 | key: ${{ runner.os }}-turborepo-ios-${{ hashFiles('yarn.lock') }} 32 | restore-keys: | 33 | ${{ runner.os }}-turborepo-ios- 34 | 35 | - name: Check turborepo cache for iOS 36 | run: | 37 | TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:ios').cache.status") 38 | 39 | if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then 40 | echo "turbo_cache_hit=1" >> $GITHUB_ENV 41 | fi 42 | 43 | - name: Cache cocoapods 44 | if: env.turbo_cache_hit != 1 45 | id: cocoapods-cache 46 | uses: actions/cache@v4 47 | with: 48 | path: | 49 | **/ios/Pods 50 | key: ${{ runner.os }}-cocoapods-${{ hashFiles('example/ios/Podfile.lock') }} 51 | restore-keys: | 52 | ${{ runner.os }}-cocoapods- 53 | 54 | - name: Install cocoapods 55 | if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true' 56 | run: | 57 | cd example/ios 58 | 59 | # Work around '[!] CocoaPods could not find compatible versions for pod "hermes-engine"' 60 | pod update hermes-engine --no-repo-update 61 | 62 | pod install 63 | env: 64 | NO_FLIPPER: 1 65 | 66 | - name: Build example for iOS 67 | run: | 68 | yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" 69 | -------------------------------------------------------------------------------- /.github/workflows/build-android.yml: -------------------------------------------------------------------------------- 1 | name: Build (Android) 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | branches: 8 | - main 9 | workflow_dispatch: 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | env: 15 | TURBO_CACHE_DIR: .turbo/android 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | 21 | - name: Generate 22 | uses: ./.github/actions/generate 23 | with: 24 | platform: android 25 | release: false 26 | 27 | - name: Cache turborepo for Android 28 | uses: actions/cache@v4 29 | with: 30 | path: ${{ env.TURBO_CACHE_DIR }} 31 | key: ${{ runner.os }}-turborepo-android-${{ hashFiles('yarn.lock') }} 32 | restore-keys: | 33 | ${{ runner.os }}-turborepo-android- 34 | 35 | - name: Check turborepo cache for Android 36 | run: | 37 | TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:android').cache.status") 38 | 39 | if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then 40 | echo "turbo_cache_hit=1" >> $GITHUB_ENV 41 | fi 42 | 43 | - name: Install JDK 44 | if: env.turbo_cache_hit != 1 45 | uses: actions/setup-java@v3 46 | with: 47 | distribution: 'zulu' 48 | java-version: '17' 49 | 50 | - name: Finalize Android SDK 51 | if: env.turbo_cache_hit != 1 52 | run: | 53 | /bin/bash -c "yes | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --licenses > /dev/null" 54 | 55 | - name: Cache Gradle 56 | if: env.turbo_cache_hit != 1 57 | uses: actions/cache@v4 58 | with: 59 | path: | 60 | ~/.gradle/wrapper 61 | ~/.gradle/caches 62 | key: ${{ runner.os }}-gradle-${{ hashFiles('example/android/gradle/wrapper/gradle-wrapper.properties') }} 63 | restore-keys: | 64 | ${{ runner.os }}-gradle- 65 | 66 | - name: Build example for Android 67 | env: 68 | JAVA_OPTS: "-XX:MaxHeapSize=6g" 69 | run: | 70 | yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" 71 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | import installer from './NativeReactNativeMatrixSdk'; 3 | 4 | // Register the rust crate with Hermes 5 | // - the boolean flag ensures this loads exactly once, even if the JS 6 | // code is reloaded (e.g. during development with metro). 7 | let rustInstalled = false; 8 | if (!rustInstalled) { 9 | installer.installRustCrate(); 10 | rustInstalled = true; 11 | } 12 | 13 | // Export the generated bindings to the app. 14 | export * from './generated/matrix_sdk'; 15 | export * from './generated/matrix_sdk_base'; 16 | export * from './generated/matrix_sdk_common'; 17 | export * from './generated/matrix_sdk_crypto'; 18 | export * from './generated/matrix_sdk_ffi'; 19 | export * from './generated/matrix_sdk_ui'; 20 | 21 | // Now import the bindings so we can: 22 | // - intialize them 23 | // - export them as namespaced objects as the default export. 24 | import * as matrix_sdk from './generated/matrix_sdk'; 25 | import * as matrix_sdk_base from './generated/matrix_sdk_base'; 26 | import * as matrix_sdk_common from './generated/matrix_sdk_common'; 27 | import * as matrix_sdk_crypto from './generated/matrix_sdk_crypto'; 28 | import * as matrix_sdk_ffi from './generated/matrix_sdk_ffi'; 29 | import * as matrix_sdk_ui from './generated/matrix_sdk_ui'; 30 | 31 | // Initialize the generated bindings: mostly checksums, but also callbacks. 32 | // - the boolean flag ensures this loads exactly once, even if the JS code 33 | // is reloaded (e.g. during development with metro). 34 | let initialized = false; 35 | if (!initialized) { 36 | matrix_sdk.default.initialize(); 37 | matrix_sdk_base.default.initialize(); 38 | matrix_sdk_common.default.initialize(); 39 | matrix_sdk_crypto.default.initialize(); 40 | matrix_sdk_ffi.default.initialize(); 41 | matrix_sdk_ui.default.initialize(); 42 | initialized = true; 43 | } 44 | 45 | // This provides parity with the index.web.ts version of this file. 46 | // The web version relies on an asynchronous fetch, which this doesn't 47 | // need, so we just no-op. 48 | export async function uniffiInitAsync() { 49 | // NOOP. 50 | } 51 | 52 | // Export the crates as individually namespaced objects. 53 | export default { 54 | matrix_sdk, 55 | matrix_sdk_base, 56 | matrix_sdk_common, 57 | matrix_sdk_crypto, 58 | matrix_sdk_ffi, 59 | matrix_sdk_ui, 60 | }; 61 | 62 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExampleTests/ReactNativeMatrixSdkExampleTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface ReactNativeMatrixSdkExampleTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation ReactNativeMatrixSdkExampleTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction( 38 | ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 39 | if (level >= RCTLogLevelError) { 40 | redboxError = message; 41 | } 42 | }); 43 | #endif 44 | 45 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 46 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 48 | 49 | foundElement = [self findSubviewInView:vc.view 50 | matching:^BOOL(UIView *view) { 51 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 52 | return YES; 53 | } 54 | return NO; 55 | }]; 56 | } 57 | 58 | #ifdef DEBUG 59 | RCTSetLogFunction(RCTDefaultLogFunction); 60 | #endif 61 | 62 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 63 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /.github/actions/generate/action.yml: -------------------------------------------------------------------------------- 1 | name: Generate 2 | description: Set up dependencies and regenerate the bindings 3 | 4 | inputs: 5 | platform: 6 | description: One of android, ios 7 | required: true 8 | release: 9 | description: Whether to build in release mode, one of true, false 10 | default: "false" 11 | 12 | runs: 13 | using: composite 14 | steps: 15 | - name: Setup JS 16 | uses: ./.github/actions/setup-js 17 | 18 | - name: Setup Rust (Android) 19 | if: ${{ inputs.platform == 'android' }} 20 | uses: dtolnay/rust-toolchain@stable 21 | with: 22 | targets: aarch64-linux-android,armv7-linux-androideabi,i686-linux-android,x86_64-linux-android 23 | 24 | - name: Setup Rust (iOS) 25 | if: ${{ inputs.platform == 'ios' }} 26 | uses: dtolnay/rust-toolchain@stable 27 | with: 28 | targets: aarch64-apple-ios,aarch64-apple-ios-sim,x86_64-apple-ios 29 | 30 | - name: Install cargo-ndk 31 | if: ${{ inputs.platform == 'android' }} 32 | shell: bash 33 | run: cargo install cargo-ndk --version 3.5.4 34 | 35 | - name: Install clang-format 36 | if: ${{ inputs.platform == 'ios' }} 37 | shell: bash 38 | run: brew install clang-format 39 | 40 | - name: Write .xcode.env.local 41 | if: ${{ inputs.platform == 'ios' }} 42 | shell: bash 43 | run: | 44 | # Work around for https://github.com/facebook/react-native/issues/35657 45 | echo "export NODE_BINARY=$(which node)" >> example/ios/.xcode.env.local 46 | cat example/ios/.xcode.env.local 47 | 48 | - name: Generate 49 | shell: bash 50 | env: 51 | INFIX: ${{ inputs.release == 'true' && ':release' || '' }} 52 | SUFFIX: ${{ inputs.platform == 'android' && ':android' || ':ios' }} 53 | run: 54 | yarn generate$INFIX$SUFFIX 55 | 56 | - name: Free space 57 | shell: bash 58 | run: rm -rf rust_modules 59 | 60 | - name: Check if repository is dirty 61 | shell: bash 62 | env: 63 | EXCLUDE: ${{ inputs.platform == 'android' && 'ios' || 'android' }} 64 | run: | 65 | if [[ -n "$(git status --porcelain | grep -v ". $EXCLUDE" | grep -v swift | grep -v example/ios/Podfile.lock)" ]]; then 66 | >&2 echo "Found unexpected changes in repository after generating" 67 | git status --short 68 | git diff 69 | exit 1 70 | fi 71 | -------------------------------------------------------------------------------- /cpp/generated/matrix_sdk_ui.hpp: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the 2 | // `uniffi-bindgen-react-native` crate. Trust me, you don't want to mess with 3 | // it! 4 | #pragma once 5 | #include "UniffiCallInvoker.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace react = facebook::react; 13 | namespace jsi = facebook::jsi; 14 | 15 | class NativeMatrixSdkUi : public jsi::HostObject { 16 | private: 17 | // For calling back into JS from Rust. 18 | std::shared_ptr callInvoker; 19 | 20 | protected: 21 | std::map props; 22 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_byte_length( 23 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 24 | size_t count); 25 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 26 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 27 | size_t count); 28 | jsi::Value cpp_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 29 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 30 | size_t count); 31 | jsi::Value cpp_ffi_matrix_sdk_ui_uniffi_contract_version( 32 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 33 | size_t count); 34 | 35 | public: 36 | NativeMatrixSdkUi( 37 | jsi::Runtime &rt, 38 | std::shared_ptr callInvoker); 39 | virtual ~NativeMatrixSdkUi(); 40 | 41 | /** 42 | * The entry point into the crate. 43 | * 44 | * React Native must call `NativeMatrixSdkUi.registerModule(rt, callInvoker)` 45 | * before using the Javascript interface. 46 | */ 47 | static void registerModule(jsi::Runtime &rt, 48 | std::shared_ptr callInvoker); 49 | 50 | /** 51 | * Some cleanup into the crate goes here. 52 | * 53 | * Current implementation is empty, however, this is not guaranteed to always 54 | * be the case. 55 | * 56 | * Clients should call `NativeMatrixSdkUi.unregisterModule(rt)` after final 57 | * use where possible. 58 | */ 59 | static void unregisterModule(jsi::Runtime &rt); 60 | 61 | virtual jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name); 62 | virtual void set(jsi::Runtime &rt, const jsi::PropNameID &name, 63 | const jsi::Value &value); 64 | virtual std::vector getPropertyNames(jsi::Runtime &rt); 65 | }; -------------------------------------------------------------------------------- /cpp/generated/matrix_sdk_base.hpp: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the 2 | // `uniffi-bindgen-react-native` crate. Trust me, you don't want to mess with 3 | // it! 4 | #pragma once 5 | #include "UniffiCallInvoker.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace react = facebook::react; 13 | namespace jsi = facebook::jsi; 14 | 15 | class NativeMatrixSdkBase : public jsi::HostObject { 16 | private: 17 | // For calling back into JS from Rust. 18 | std::shared_ptr callInvoker; 19 | 20 | protected: 21 | std::map props; 22 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_byte_length( 23 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 24 | size_t count); 25 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 26 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 27 | size_t count); 28 | jsi::Value cpp_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 29 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 30 | size_t count); 31 | jsi::Value cpp_ffi_matrix_sdk_base_uniffi_contract_version( 32 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 33 | size_t count); 34 | 35 | public: 36 | NativeMatrixSdkBase( 37 | jsi::Runtime &rt, 38 | std::shared_ptr callInvoker); 39 | virtual ~NativeMatrixSdkBase(); 40 | 41 | /** 42 | * The entry point into the crate. 43 | * 44 | * React Native must call `NativeMatrixSdkBase.registerModule(rt, 45 | * callInvoker)` before using the Javascript interface. 46 | */ 47 | static void registerModule(jsi::Runtime &rt, 48 | std::shared_ptr callInvoker); 49 | 50 | /** 51 | * Some cleanup into the crate goes here. 52 | * 53 | * Current implementation is empty, however, this is not guaranteed to always 54 | * be the case. 55 | * 56 | * Clients should call `NativeMatrixSdkBase.unregisterModule(rt)` after final 57 | * use where possible. 58 | */ 59 | static void unregisterModule(jsi::Runtime &rt); 60 | 61 | virtual jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name); 62 | virtual void set(jsi::Runtime &rt, const jsi::PropNameID &name, 63 | const jsi::Value &value); 64 | virtual std::vector getPropertyNames(jsi::Runtime &rt); 65 | }; -------------------------------------------------------------------------------- /cpp/generated/matrix_sdk_common.hpp: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the 2 | // `uniffi-bindgen-react-native` crate. Trust me, you don't want to mess with 3 | // it! 4 | #pragma once 5 | #include "UniffiCallInvoker.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace react = facebook::react; 13 | namespace jsi = facebook::jsi; 14 | 15 | class NativeMatrixSdkCommon : public jsi::HostObject { 16 | private: 17 | // For calling back into JS from Rust. 18 | std::shared_ptr callInvoker; 19 | 20 | protected: 21 | std::map props; 22 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_byte_length( 23 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 24 | size_t count); 25 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 26 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 27 | size_t count); 28 | jsi::Value cpp_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 29 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 30 | size_t count); 31 | jsi::Value cpp_ffi_matrix_sdk_common_uniffi_contract_version( 32 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 33 | size_t count); 34 | 35 | public: 36 | NativeMatrixSdkCommon( 37 | jsi::Runtime &rt, 38 | std::shared_ptr callInvoker); 39 | virtual ~NativeMatrixSdkCommon(); 40 | 41 | /** 42 | * The entry point into the crate. 43 | * 44 | * React Native must call `NativeMatrixSdkCommon.registerModule(rt, 45 | * callInvoker)` before using the Javascript interface. 46 | */ 47 | static void registerModule(jsi::Runtime &rt, 48 | std::shared_ptr callInvoker); 49 | 50 | /** 51 | * Some cleanup into the crate goes here. 52 | * 53 | * Current implementation is empty, however, this is not guaranteed to always 54 | * be the case. 55 | * 56 | * Clients should call `NativeMatrixSdkCommon.unregisterModule(rt)` after 57 | * final use where possible. 58 | */ 59 | static void unregisterModule(jsi::Runtime &rt); 60 | 61 | virtual jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name); 62 | virtual void set(jsi::Runtime &rt, const jsi::PropNameID &name, 63 | const jsi::Value &value); 64 | virtual std::vector getPropertyNames(jsi::Runtime &rt); 65 | }; -------------------------------------------------------------------------------- /cpp/generated/matrix_sdk_crypto.hpp: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the 2 | // `uniffi-bindgen-react-native` crate. Trust me, you don't want to mess with 3 | // it! 4 | #pragma once 5 | #include "UniffiCallInvoker.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace react = facebook::react; 13 | namespace jsi = facebook::jsi; 14 | 15 | class NativeMatrixSdkCrypto : public jsi::HostObject { 16 | private: 17 | // For calling back into JS from Rust. 18 | std::shared_ptr callInvoker; 19 | 20 | protected: 21 | std::map props; 22 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_byte_length( 23 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 24 | size_t count); 25 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 26 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 27 | size_t count); 28 | jsi::Value cpp_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 29 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 30 | size_t count); 31 | jsi::Value cpp_ffi_matrix_sdk_crypto_uniffi_contract_version( 32 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 33 | size_t count); 34 | 35 | public: 36 | NativeMatrixSdkCrypto( 37 | jsi::Runtime &rt, 38 | std::shared_ptr callInvoker); 39 | virtual ~NativeMatrixSdkCrypto(); 40 | 41 | /** 42 | * The entry point into the crate. 43 | * 44 | * React Native must call `NativeMatrixSdkCrypto.registerModule(rt, 45 | * callInvoker)` before using the Javascript interface. 46 | */ 47 | static void registerModule(jsi::Runtime &rt, 48 | std::shared_ptr callInvoker); 49 | 50 | /** 51 | * Some cleanup into the crate goes here. 52 | * 53 | * Current implementation is empty, however, this is not guaranteed to always 54 | * be the case. 55 | * 56 | * Clients should call `NativeMatrixSdkCrypto.unregisterModule(rt)` after 57 | * final use where possible. 58 | */ 59 | static void unregisterModule(jsi::Runtime &rt); 60 | 61 | virtual jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name); 62 | virtual void set(jsi::Runtime &rt, const jsi::PropNameID &name, 63 | const jsi::Value &value); 64 | virtual std::vector getPropertyNames(jsi::Runtime &rt); 65 | }; -------------------------------------------------------------------------------- /scripts/download-binaries.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const https = require('https'); 6 | const { execSync } = require('child_process'); 7 | const tar = require('tar'); 8 | 9 | const PACKAGE_JSON = require('../package.json'); 10 | const VERSION = PACKAGE_JSON.version; 11 | const REPO = 'unomed-dev/react-native-matrix-sdk'; 12 | 13 | async function downloadFile(url, dest) { 14 | return new Promise((resolve, reject) => { 15 | const file = fs.createWriteStream(dest); 16 | https.get(url, (response) => { 17 | if (response.statusCode === 302 || response.statusCode === 301) { 18 | // Follow redirect 19 | https.get(response.headers.location, (redirectResponse) => { 20 | redirectResponse.pipe(file); 21 | file.on('finish', () => { 22 | file.close(resolve); 23 | }); 24 | }).on('error', reject); 25 | } else if (response.statusCode === 200) { 26 | response.pipe(file); 27 | file.on('finish', () => { 28 | file.close(resolve); 29 | }); 30 | } else { 31 | reject(new Error(`HTTP ${response.statusCode}`)); 32 | } 33 | }).on('error', reject); 34 | }); 35 | } 36 | 37 | async function downloadBinaries() { 38 | const buildDir = path.join(__dirname, '..', 'build'); 39 | 40 | // Check if binaries already exist 41 | if (fs.existsSync(path.join(buildDir, 'RnMatrixRustSdk.xcframework'))) { 42 | console.log('Binaries already exist, skipping download.'); 43 | return; 44 | } 45 | 46 | console.log(`Downloading binaries for ${VERSION}...`); 47 | 48 | const releaseUrl = `https://github.com/${REPO}/releases/download/${VERSION}/binaries.tar.gz`; 49 | const tempFile = path.join(__dirname, '..', 'binaries.tar.gz'); 50 | 51 | try { 52 | // Download the binary archive 53 | console.log(`Downloading from ${releaseUrl}...`); 54 | await downloadFile(releaseUrl, tempFile); 55 | 56 | // Extract the archive 57 | console.log('Extracting binaries...'); 58 | await tar.x({ 59 | file: tempFile, 60 | cwd: path.join(__dirname, '..'), 61 | }); 62 | 63 | // Clean up 64 | fs.unlinkSync(tempFile); 65 | 66 | console.log('Binaries downloaded successfully!'); 67 | } catch (error) { 68 | console.error('Failed to download binaries:', error.message); 69 | console.error('You may need to build the binaries locally using:'); 70 | console.error(' yarn generate:release'); 71 | // Exit gracefully if binaries do not exist 72 | process.exit(0); 73 | } 74 | } 75 | 76 | if (require.main === module) { 77 | downloadBinaries().catch(console.error); 78 | } 79 | 80 | module.exports = { downloadBinaries }; -------------------------------------------------------------------------------- /ios/ReactNativeMatrixSdk.mm: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | #import "ReactNativeMatrixSdk.h" 3 | 4 | namespace uniffi_generated { 5 | using namespace facebook::react; 6 | /** 7 | * ObjC++ class for module 'NativeReactNativeMatrixSdk' 8 | */ 9 | class JSI_EXPORT NativeReactNativeMatrixSdkSpecJSI : public ObjCTurboModule { 10 | public: 11 | NativeReactNativeMatrixSdkSpecJSI(const ObjCTurboModule::InitParams ¶ms); 12 | std::shared_ptr callInvoker; 13 | }; 14 | 15 | static facebook::jsi::Value __hostFunction_ReactNativeMatrixSdk_installRustCrate(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { 16 | auto& tm = static_cast(turboModule); 17 | auto jsInvoker = tm.callInvoker; 18 | uint8_t result = unomed_reactnativematrixsdk::installRustCrate(rt, jsInvoker); 19 | return facebook::jsi::Value(rt, result); 20 | } 21 | static facebook::jsi::Value __hostFunction_ReactNativeMatrixSdk_cleanupRustCrate(facebook::jsi::Runtime& rt, TurboModule &turboModule, const facebook::jsi::Value* args, size_t count) { 22 | uint8_t result = unomed_reactnativematrixsdk::cleanupRustCrate(rt); 23 | return facebook::jsi::Value(rt, result); 24 | } 25 | 26 | NativeReactNativeMatrixSdkSpecJSI::NativeReactNativeMatrixSdkSpecJSI(const ObjCTurboModule::InitParams ¶ms) 27 | : ObjCTurboModule(params), callInvoker(params.jsInvoker) { 28 | this->methodMap_["installRustCrate"] = MethodMetadata {1, __hostFunction_ReactNativeMatrixSdk_installRustCrate}; 29 | this->methodMap_["cleanupRustCrate"] = MethodMetadata {1, __hostFunction_ReactNativeMatrixSdk_cleanupRustCrate}; 30 | } 31 | } // namespace uniffi_generated 32 | 33 | @implementation ReactNativeMatrixSdk 34 | RCT_EXPORT_MODULE() 35 | 36 | // Don't compile this code when we build for the old architecture. 37 | #ifdef RCT_NEW_ARCH_ENABLED 38 | 39 | // Automated testing checks unomed_reactnativematrixsdk 40 | // by comparing the whole line here. 41 | /* 42 | - (NSNumber *)multiply:(double)a b:(double)b { 43 | NSNumber *result = @(unomed_reactnativematrixsdk::multiply(a, b)); 44 | } 45 | */ 46 | 47 | - (NSNumber *)installRustCrate { 48 | @throw [NSException exceptionWithName:@"UnreachableException" 49 | reason:@"This method should never be called." 50 | userInfo:nil]; 51 | } 52 | 53 | - (NSNumber *)cleanupRustCrate { 54 | @throw [NSException exceptionWithName:@"UnreachableException" 55 | reason:@"This method should never be called." 56 | userInfo:nil]; 57 | } 58 | 59 | - (std::shared_ptr)getTurboModule: 60 | (const facebook::react::ObjCTurboModule::InitParams &)params 61 | { 62 | return std::make_shared(params); 63 | } 64 | #endif 65 | 66 | @end -------------------------------------------------------------------------------- /android/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # Generated by uniffi-bindgen-react-native 2 | cmake_minimum_required(VERSION 3.9.0) 3 | project(ReactNativeMatrixSdk) 4 | 5 | set (CMAKE_VERBOSE_MAKEFILE ON) 6 | set (CMAKE_CXX_STANDARD 17) 7 | 8 | # Resolve the path to the uniffi-bindgen-react-native package 9 | execute_process( 10 | COMMAND node -p "require.resolve('uniffi-bindgen-react-native/package.json')" 11 | OUTPUT_VARIABLE UNIFFI_BINDGEN_PATH 12 | OUTPUT_STRIP_TRAILING_WHITESPACE 13 | ) 14 | # Get the directory; get_filename_component and cmake_path will normalize 15 | # paths with Windows path separators. 16 | get_filename_component(UNIFFI_BINDGEN_PATH "${UNIFFI_BINDGEN_PATH}" DIRECTORY) 17 | 18 | # Specifies a path to native header files. 19 | include_directories( 20 | ../cpp 21 | ../cpp/generated 22 | 23 | ${UNIFFI_BINDGEN_PATH}/cpp/includes 24 | ) 25 | 26 | add_library(unomed-react-native-matrix-sdk SHARED 27 | ../cpp/unomed-react-native-matrix-sdk.cpp 28 | ../cpp/generated/matrix_sdk.cpp 29 | ../cpp/generated/matrix_sdk_base.cpp 30 | ../cpp/generated/matrix_sdk_common.cpp 31 | ../cpp/generated/matrix_sdk_crypto.cpp 32 | ../cpp/generated/matrix_sdk_ffi.cpp 33 | ../cpp/generated/matrix_sdk_ui.cpp 34 | cpp-adapter.cpp 35 | ) 36 | 37 | # Set C++ compiler flags 38 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2") 39 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions") 40 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti") 41 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all") 42 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") 43 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") 44 | 45 | cmake_path( 46 | SET MY_RUST_LIB 47 | ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libmatrix_sdk_ffi.so 48 | NORMALIZE 49 | ) 50 | add_library(my_rust_lib SHARED IMPORTED) 51 | set_target_properties(my_rust_lib PROPERTIES IMPORTED_LOCATION ${MY_RUST_LIB} IMPORTED_NO_SONAME ON) 52 | 53 | # Add ReactAndroid libraries, being careful to account for different versions. 54 | find_package(ReactAndroid REQUIRED CONFIG) 55 | find_library(LOGCAT log) 56 | 57 | # REACTNATIVE_MERGED_SO seems to be only be set in a build.gradle.kt file, 58 | # which we don't use. Thus falling back to version number sniffing. 59 | if (ReactAndroid_VERSION_MINOR GREATER_EQUAL 76) 60 | set(REACTNATIVE_MERGED_SO true) 61 | endif() 62 | 63 | # https://github.com/react-native-community/discussions-and-proposals/discussions/816 64 | # This if-then-else can be removed once this library does not support version below 0.76 65 | if (REACTNATIVE_MERGED_SO) 66 | target_link_libraries(unomed-react-native-matrix-sdk ReactAndroid::reactnative) 67 | else() 68 | target_link_libraries(unomed-react-native-matrix-sdk 69 | ReactAndroid::turbomodulejsijni 70 | ReactAndroid::react_nativemodule_core 71 | ) 72 | endif() 73 | 74 | find_package(fbjni REQUIRED CONFIG) 75 | target_link_libraries( 76 | unomed-react-native-matrix-sdk 77 | fbjni::fbjni 78 | ReactAndroid::jsi 79 | ${LOGCAT} 80 | my_rust_lib 81 | ) 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-matrix-sdk 2 | 3 | ⚡️ FFI bindings for [matrix-rust-sdk] in a React Native Turbo Module ⚡️ 4 | 5 | [![lint](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/lint.yml/badge.svg)](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/lint.yml) 6 | [![library](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/library.yml/badge.svg)](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/library.yml) 7 | [![android](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/build-android.yml/badge.svg)](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/build-android.yml) 8 | [![ios](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/build-ios.yml/badge.svg)](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/build-ios.yml) 9 | [![android](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/build-release.yml/badge.svg)](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/build-release.yml) 10 | [![NPM install](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/install.yml/badge.svg)](https://github.com/unomed-dev/react-native-matrix-sdk/actions/workflows/install.yml) 11 | 12 | Powered by [uniffi-bindgen-react-native] and [create-react-native-library]. 13 | 14 | 15 | ## Installation 16 | 17 | ### Installation into your own project 18 | 19 | This package is available in the [npm registry]. 20 | 21 | ```sh 22 | npm i @unomed/react-native-matrix-sdk 23 | yarn add @unomed/react-native-matrix-sdk 24 | ``` 25 | 26 | 27 | ### Installation from local checkout 28 | 29 | Clone the repository into a sibling folder of your app and then install the package using 30 | a relative path. 31 | 32 | ```sh 33 | npm add ../react-native-matrix-sdk 34 | ``` 35 | 36 | You might have to run `yarn prepare` in case it's not executed by default. Additionally you 37 | need to change `metro.config.js` to find and watch the module's source code. 38 | 39 | ```js 40 | const config = { 41 | resolver: { 42 | extraNodeModules: { 43 | 'react-native-matrix-sdk': path.resolve(__dirname, '../react-native-matrix-sdk'), 44 | }, ... 45 | }, 46 | watchFolders: [ 47 | path.resolve(__dirname, '../react-native-matrix-sdk'), ... 48 | ] 49 | }; 50 | ``` 51 | 52 | On the first build or any time you update the version of matrix-rust-sdk, you'll have 53 | to rebuild the Rust code and regenerate the module with 54 | 55 | ```sh 56 | yarn generate 57 | ``` 58 | 59 | 60 | ## Usage 61 | 62 | See [src/index.ts] for the module's full API. You may also find a usage example 63 | in [example/src/App.tsx]. 64 | 65 | 66 | ## Contributing 67 | 68 | See the [contributing guide] to learn about the development and contribution workflow. 69 | 70 | 71 | ## License 72 | 73 | Apache-2.0 74 | 75 | 76 | [contributing guide]: CONTRIBUTING.md 77 | [create-react-native-library]: https://github.com/callstack/react-native-builder-bob 78 | [example/src/App.tsx]: example/src/App.tsx 79 | [matrix-rust-sdk]: https://github.com/matrix-org/matrix-rust-sdk 80 | [npm registry]: https://www.npmjs.com/package/@unomed/react-native-matrix-sdk 81 | [src/index.ts]: src/index.ts 82 | [uniffi-bindgen-react-native]: https://github.com/jhugman/uniffi-bindgen-react-native 83 | -------------------------------------------------------------------------------- /example/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /scripts/sort-uniffi-calls.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /* 3 | * Script to sort uniffiEnsureInitialized() calls in generated Kotlin bindings 4 | * 5 | * This fixes non-deterministic ordering caused by HashMap iteration in uniffi v0.29.4 6 | * See: https://github.com/mozilla/uniffi-rs (potential issue to be reported) 7 | */ 8 | 9 | const fs = require('fs'); 10 | const path = require('path'); 11 | 12 | const KOTLIN_FILE_PATH = 'android/src/main/java/org/matrix/rustcomponents/sdk/matrix_sdk_ffi.kt'; 13 | 14 | function sortUniffiCalls() { 15 | const filePath = path.resolve(KOTLIN_FILE_PATH); 16 | 17 | if (!fs.existsSync(filePath)) { 18 | console.error(`Error: File not found: ${filePath}`); 19 | process.exit(1); 20 | } 21 | 22 | let content = fs.readFileSync(filePath, 'utf8'); 23 | const lines = content.split('\n'); 24 | 25 | // Find the indices of uniffiEnsureInitialized calls 26 | const uniffiIndices = []; 27 | const uniffiCalls = []; 28 | 29 | for (let i = 0; i < lines.length; i++) { 30 | const line = lines[i]; 31 | if (line.includes('uniffi.') && line.includes('.uniffiEnsureInitialized()')) { 32 | uniffiIndices.push(i); 33 | // Extract just the call part, preserving original indentation 34 | const match = line.match(/^(\s*)(uniffi\.[^.]+\.uniffiEnsureInitialized\(\))/); 35 | if (match) { 36 | uniffiCalls.push({ 37 | indentation: match[1], 38 | call: match[2], 39 | originalIndex: i 40 | }); 41 | } 42 | } 43 | } 44 | 45 | if (uniffiCalls.length === 0) { 46 | console.log('No uniffiEnsureInitialized calls found'); 47 | return; 48 | } 49 | 50 | // Sort the calls alphabetically by module name 51 | const sortedCalls = [...uniffiCalls].sort((a, b) => { 52 | const matchA = a.call.match(/uniffi\.([^.]+)\.uniffiEnsureInitialized/); 53 | const matchB = b.call.match(/uniffi\.([^.]+)\.uniffiEnsureInitialized/); 54 | const moduleA = matchA ? matchA[1] : ''; 55 | const moduleB = matchB ? matchB[1] : ''; 56 | return moduleA.localeCompare(moduleB); 57 | }); 58 | 59 | // Check if order changed 60 | const orderChanged = sortedCalls.some((call, index) => 61 | call.originalIndex !== uniffiCalls[index].originalIndex 62 | ); 63 | 64 | if (!orderChanged) { 65 | console.log('✅ uniffiEnsureInitialized calls are already sorted'); 66 | return; 67 | } 68 | 69 | // Replace the lines with sorted versions 70 | for (let i = 0; i < uniffiIndices.length; i++) { 71 | const lineIndex = uniffiIndices[i]; 72 | const sortedCall = sortedCalls[i]; 73 | if (sortedCall) { 74 | lines[lineIndex] = `${sortedCall.indentation}${sortedCall.call}`; 75 | } 76 | } 77 | 78 | const newContent = lines.join('\n'); 79 | fs.writeFileSync(filePath, newContent, 'utf8'); 80 | 81 | console.log(`✅ Sorted ${uniffiCalls.length} uniffiEnsureInitialized calls in ${KOTLIN_FILE_PATH}`); 82 | 83 | // Show the sorted order for verification 84 | const moduleNames = sortedCalls 85 | .map(call => { 86 | const match = call.call.match(/uniffi\.([^.]+)\.uniffiEnsureInitialized/); 87 | return match ? match[1] : null; 88 | }) 89 | .filter(Boolean); 90 | console.log(`📋 Order: ${moduleNames.join(' → ')}`); 91 | } 92 | 93 | if (require.main === module) { 94 | sortUniffiCalls(); 95 | } 96 | 97 | module.exports = { sortUniffiCalls }; -------------------------------------------------------------------------------- /example/Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | CFPropertyList (3.0.7) 5 | base64 6 | nkf 7 | rexml 8 | activesupport (7.2.2.1) 9 | base64 10 | benchmark (>= 0.3) 11 | bigdecimal 12 | concurrent-ruby (~> 1.0, >= 1.3.1) 13 | connection_pool (>= 2.2.5) 14 | drb 15 | i18n (>= 1.6, < 2) 16 | logger (>= 1.4.2) 17 | minitest (>= 5.1) 18 | securerandom (>= 0.3) 19 | tzinfo (~> 2.0, >= 2.0.5) 20 | addressable (2.8.7) 21 | public_suffix (>= 2.0.2, < 7.0) 22 | algoliasearch (1.27.5) 23 | httpclient (~> 2.8, >= 2.8.3) 24 | json (>= 1.5.1) 25 | atomos (0.1.3) 26 | base64 (0.2.0) 27 | benchmark (0.4.0) 28 | bigdecimal (3.1.8) 29 | claide (1.1.0) 30 | cocoapods (1.15.2) 31 | addressable (~> 2.8) 32 | claide (>= 1.0.2, < 2.0) 33 | cocoapods-core (= 1.15.2) 34 | cocoapods-deintegrate (>= 1.0.3, < 2.0) 35 | cocoapods-downloader (>= 2.1, < 3.0) 36 | cocoapods-plugins (>= 1.0.0, < 2.0) 37 | cocoapods-search (>= 1.0.0, < 2.0) 38 | cocoapods-trunk (>= 1.6.0, < 2.0) 39 | cocoapods-try (>= 1.1.0, < 2.0) 40 | colored2 (~> 3.1) 41 | escape (~> 0.0.4) 42 | fourflusher (>= 2.3.0, < 3.0) 43 | gh_inspector (~> 1.0) 44 | molinillo (~> 0.8.0) 45 | nap (~> 1.0) 46 | ruby-macho (>= 2.3.0, < 3.0) 47 | xcodeproj (>= 1.23.0, < 2.0) 48 | cocoapods-core (1.15.2) 49 | activesupport (>= 5.0, < 8) 50 | addressable (~> 2.8) 51 | algoliasearch (~> 1.0) 52 | concurrent-ruby (~> 1.1) 53 | fuzzy_match (~> 2.0.4) 54 | nap (~> 1.0) 55 | netrc (~> 0.11) 56 | public_suffix (~> 4.0) 57 | typhoeus (~> 1.0) 58 | cocoapods-deintegrate (1.0.5) 59 | cocoapods-downloader (2.1) 60 | cocoapods-plugins (1.0.0) 61 | nap 62 | cocoapods-search (1.0.1) 63 | cocoapods-trunk (1.6.0) 64 | nap (>= 0.8, < 2.0) 65 | netrc (~> 0.11) 66 | cocoapods-try (1.2.0) 67 | colored2 (3.1.2) 68 | concurrent-ruby (1.3.4) 69 | connection_pool (2.4.1) 70 | drb (2.2.1) 71 | escape (0.0.4) 72 | ethon (0.16.0) 73 | ffi (>= 1.15.0) 74 | ffi (1.17.0) 75 | fourflusher (2.3.1) 76 | fuzzy_match (2.0.4) 77 | gh_inspector (1.1.3) 78 | httpclient (2.8.3) 79 | i18n (1.14.6) 80 | concurrent-ruby (~> 1.0) 81 | json (2.9.1) 82 | logger (1.6.4) 83 | minitest (5.25.4) 84 | molinillo (0.8.0) 85 | nanaimo (0.3.0) 86 | nap (1.1.0) 87 | netrc (0.11.0) 88 | nkf (0.2.0) 89 | public_suffix (4.0.7) 90 | rexml (3.4.0) 91 | ruby-macho (2.5.1) 92 | securerandom (0.4.1) 93 | typhoeus (1.4.1) 94 | ethon (>= 0.9.0) 95 | tzinfo (2.0.6) 96 | concurrent-ruby (~> 1.0) 97 | xcodeproj (1.25.1) 98 | CFPropertyList (>= 2.3.3, < 4.0) 99 | atomos (~> 0.1.3) 100 | claide (>= 1.0.2, < 2.0) 101 | colored2 (~> 3.1) 102 | nanaimo (~> 0.3.0) 103 | rexml (>= 3.3.6, < 4.0) 104 | 105 | PLATFORMS 106 | ruby 107 | 108 | DEPENDENCIES 109 | activesupport (>= 6.1.7.5, != 7.1.0) 110 | cocoapods (>= 1.13, != 1.15.1, != 1.15.0) 111 | concurrent-ruby (< 1.3.5) 112 | xcodeproj (< 1.26.0) 113 | 114 | RUBY VERSION 115 | ruby 3.3.5p100 116 | 117 | BUNDLED WITH 118 | 2.5.19 119 | -------------------------------------------------------------------------------- /cpp/generated/matrix_sdk.hpp: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the 2 | // `uniffi-bindgen-react-native` crate. Trust me, you don't want to mess with 3 | // it! 4 | #pragma once 5 | #include "UniffiCallInvoker.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | namespace react = facebook::react; 13 | namespace jsi = facebook::jsi; 14 | 15 | class NativeMatrixSdk : public jsi::HostObject { 16 | private: 17 | // For calling back into JS from Rust. 18 | std::shared_ptr callInvoker; 19 | 20 | protected: 21 | std::map props; 22 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_byte_length( 23 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 24 | size_t count); 25 | jsi::Value cpp_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 26 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 27 | size_t count); 28 | jsi::Value cpp_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 29 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 30 | size_t count); 31 | jsi::Value cpp_uniffi_matrix_sdk_fn_clone_oauthauthorizationdata( 32 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 33 | size_t count); 34 | jsi::Value cpp_uniffi_matrix_sdk_fn_free_oauthauthorizationdata( 35 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 36 | size_t count); 37 | jsi::Value cpp_uniffi_matrix_sdk_fn_method_oauthauthorizationdata_login_url( 38 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 39 | size_t count); 40 | jsi::Value 41 | cpp_uniffi_matrix_sdk_checksum_method_oauthauthorizationdata_login_url( 42 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 43 | size_t count); 44 | jsi::Value cpp_ffi_matrix_sdk_uniffi_contract_version( 45 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 46 | size_t count); 47 | jsi::Value 48 | cpp_uniffi_internal_fn_method_oauthauthorizationdata_ffi__bless_pointer( 49 | jsi::Runtime &rt, const jsi::Value &thisVal, const jsi::Value *args, 50 | size_t count); 51 | 52 | public: 53 | NativeMatrixSdk( 54 | jsi::Runtime &rt, 55 | std::shared_ptr callInvoker); 56 | virtual ~NativeMatrixSdk(); 57 | 58 | /** 59 | * The entry point into the crate. 60 | * 61 | * React Native must call `NativeMatrixSdk.registerModule(rt, callInvoker)` 62 | * before using the Javascript interface. 63 | */ 64 | static void registerModule(jsi::Runtime &rt, 65 | std::shared_ptr callInvoker); 66 | 67 | /** 68 | * Some cleanup into the crate goes here. 69 | * 70 | * Current implementation is empty, however, this is not guaranteed to always 71 | * be the case. 72 | * 73 | * Clients should call `NativeMatrixSdk.unregisterModule(rt)` after final use 74 | * where possible. 75 | */ 76 | static void unregisterModule(jsi::Runtime &rt); 77 | 78 | virtual jsi::Value get(jsi::Runtime &rt, const jsi::PropNameID &name); 79 | virtual void set(jsi::Runtime &rt, const jsi::PropNameID &name, 80 | const jsi::Value &value); 81 | virtual std::vector getPropertyNames(jsi::Runtime &rt); 82 | }; -------------------------------------------------------------------------------- /android/cpp-adapter.cpp: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | #include 3 | #include 4 | #include 5 | #include "unomed-react-native-matrix-sdk.h" 6 | 7 | namespace jsi = facebook::jsi; 8 | namespace react = facebook::react; 9 | 10 | // Automated testing checks Java_com_unomed_reactnativematrixsdk_ReactNativeMatrixSdkModule and unomed_reactnativematrixsdk 11 | // by comparing the whole line here. 12 | /* 13 | Java_com_unomed_reactnativematrixsdk_ReactNativeMatrixSdkModule_nativeMultiply(JNIEnv *env, jclass type, jdouble a, jdouble b) { 14 | return unomed_reactnativematrixsdk::multiply(a, b); 15 | } 16 | */ 17 | 18 | // Installer coming from ReactNativeMatrixSdkModule 19 | extern "C" 20 | JNIEXPORT jboolean JNICALL 21 | Java_com_unomed_reactnativematrixsdk_ReactNativeMatrixSdkModule_nativeInstallRustCrate( 22 | JNIEnv *env, 23 | jclass type, 24 | jlong rtPtr, 25 | jobject callInvokerHolderJavaObj 26 | ) { 27 | // https://github.com/realm/realm-js/blob/main/packages/realm/binding/android/src/main/cpp/io_realm_react_RealmReactModule.cpp#L122-L145 28 | // React Native uses the fbjni library for handling JNI, which has the concept of "hybrid objects", 29 | // which are Java objects containing a pointer to a C++ object. The CallInvokerHolder, which has the 30 | // invokeAsync method we want access to, is one such hybrid object. 31 | // Rather than reworking our code to use fbjni throughout, this code unpacks the C++ object from the Java 32 | // object `callInvokerHolderJavaObj` manually, based on reverse engineering the fbjni code. 33 | 34 | // 1. Get the Java object referred to by the mHybridData field of the Java holder object 35 | auto callInvokerHolderClass = env->GetObjectClass(callInvokerHolderJavaObj); 36 | auto hybridDataField = env->GetFieldID(callInvokerHolderClass, "mHybridData", "Lcom/facebook/jni/HybridData;"); 37 | auto hybridDataObj = env->GetObjectField(callInvokerHolderJavaObj, hybridDataField); 38 | 39 | // 2. Get the destructor Java object referred to by the mDestructor field from the myHybridData Java object 40 | auto hybridDataClass = env->FindClass("com/facebook/jni/HybridData"); 41 | auto destructorField = 42 | env->GetFieldID(hybridDataClass, "mDestructor", "Lcom/facebook/jni/HybridData$Destructor;"); 43 | auto destructorObj = env->GetObjectField(hybridDataObj, destructorField); 44 | 45 | // 3. Get the mNativePointer field from the mDestructor Java object 46 | auto destructorClass = env->FindClass("com/facebook/jni/HybridData$Destructor"); 47 | auto nativePointerField = env->GetFieldID(destructorClass, "mNativePointer", "J"); 48 | auto nativePointerValue = env->GetLongField(destructorObj, nativePointerField); 49 | 50 | // 4. Cast the mNativePointer back to its C++ type 51 | auto nativePointer = reinterpret_cast(nativePointerValue); 52 | auto jsCallInvoker = nativePointer->getCallInvoker(); 53 | 54 | auto runtime = reinterpret_cast(rtPtr); 55 | return unomed_reactnativematrixsdk::installRustCrate(*runtime, jsCallInvoker); 56 | } 57 | 58 | extern "C" 59 | JNIEXPORT jboolean JNICALL 60 | Java_com_unomed_reactnativematrixsdk_ReactNativeMatrixSdkModule_nativeCleanupRustCrate(JNIEnv *env, jclass type, jlong rtPtr) { 61 | auto runtime = reinterpret_cast(rtPtr); 62 | return unomed_reactnativematrixsdk::cleanupRustCrate(*runtime); 63 | } -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | This is a new [**React Native**] project, bootstrapped using [`@react-native-community/cli`]. 2 | 3 | 4 | # Getting Started 5 | 6 | > **Note**: Make sure you have completed the [React Native - Environment Setup] instructions up to 7 | > the "Creating a new application" step, before proceeding. 8 | 9 | 10 | ## Step 1: Start the Metro Server 11 | 12 | First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native. 13 | 14 | To start Metro, run the following command from the _root_ of your React Native project: 15 | 16 | ```bash 17 | # using npm 18 | npm start 19 | 20 | # OR using Yarn 21 | yarn start 22 | ``` 23 | 24 | 25 | ## Step 2: Start your Application 26 | 27 | Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React 28 | Native project. Run the following command to start your _Android_ or _iOS_ app: 29 | 30 | **For Android** 31 | 32 | ```bash 33 | # using npm 34 | npm run android 35 | 36 | # OR using Yarn 37 | yarn android 38 | ``` 39 | 40 | **For iOS** 41 | 42 | ```bash 43 | # using npm 44 | npm run ios 45 | 46 | # OR using Yarn 47 | yarn ios 48 | ``` 49 | 50 | If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ 51 | or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly. 52 | 53 | This is one way to run your app — you can also run it directly from within Android Studio and Xcode 54 | respectively. 55 | 56 | 57 | ## Step 3: Modifying your App 58 | 59 | Now that you have successfully run the app, let's modify it. 60 | 61 | 1. Open `App.tsx` in your text editor of choice and edit some lines. 62 | 2. For **Android**: Press the R key twice or select **"Reload"** from the 63 | **Developer Menu** (Ctrl + M (on Window and Linux) or Cmd ⌘ 64 | + M (on macOS)) to see your changes. 65 | 66 | For **iOS**: Hit Cmd ⌘ + R in your iOS Simulator to reload the app and 67 | see your changes. 68 | 69 | 70 | ## Congratulations! :tada: 71 | 72 | You've successfully run and modified your React Native App. :partying_face: 73 | 74 | 75 | ### Now what? 76 | 77 | - If you want to add this new React Native code to an existing application, check out the 78 | [Integration guide]. 79 | - If you're curious to learn more about React Native, check out the [Introduction to React Native]. 80 | 81 | 82 | # Troubleshooting 83 | 84 | If you can't get this to work, see the [Troubleshooting] page. 85 | 86 | 87 | # Learn More 88 | 89 | To learn more about React Native, take a look at the following resources: 90 | 91 | - [React Native Website] - learn more about React Native. 92 | - [Getting Started] - an **overview** of React Native and how setup your environment. 93 | - [Learn the Basics] - a **guided tour** of the React Native **basics**. 94 | - [Blog] - read the latest official React Native **Blog** posts. 95 | - [`@facebook/react-native`] - the Open Source; GitHub **repository** for React Native. 96 | 97 | 98 | [**React Native**]: https://reactnative.dev 99 | [`@facebook/react-native`]: https://github.com/facebook/react-native 100 | [`@react-native-community/cli`]: https://github.com/react-native-community/cli 101 | [Blog]: https://reactnative.dev/blog 102 | [Getting Started]: https://reactnative.dev/docs/environment-setup 103 | [Integration guide]: https://reactnative.dev/docs/integration-with-existing-apps 104 | [Introduction to React Native]: https://reactnative.dev/docs/getting-started 105 | [Learn the Basics]: https://reactnative.dev/docs/getting-started 106 | [React Native - Environment Setup]: https://reactnative.dev/docs/environment-setup 107 | [React Native Website]: https://reactnative.dev 108 | [Troubleshooting]: https://reactnative.dev/docs/troubleshooting 109 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample.xcodeproj/xcshareddata/xcschemes/ReactNativeMatrixSdkExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /example/ios/ReactNativeMatrixSdkExample/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 24 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Generated by uniffi-bindgen-react-native 2 | 3 | buildscript { 4 | // Buildscript is evaluated before everything else so we can't use getExtOrDefault 5 | def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["DummyLibForAndroid_kotlinVersion"] 6 | 7 | repositories { 8 | google() 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | classpath "com.android.tools.build:gradle:7.2.1" 14 | // noinspection DifferentKotlinGradleVersion 15 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 16 | } 17 | } 18 | 19 | def reactNativeArchitectures() { 20 | def value = rootProject.getProperties().get("reactNativeArchitectures") 21 | return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] 22 | } 23 | 24 | def isNewArchitectureEnabled() { 25 | return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" 26 | } 27 | 28 | apply plugin: "com.android.library" 29 | apply plugin: "kotlin-android" 30 | 31 | if (isNewArchitectureEnabled()) { 32 | apply plugin: "com.facebook.react" 33 | } 34 | 35 | def getExtOrDefault(name) { 36 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["ReactNativeMatrixSdk_" + name] 37 | } 38 | 39 | def getExtOrIntegerDefault(name) { 40 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactNativeMatrixSdk_" + name]).toInteger() 41 | } 42 | 43 | def supportsNamespace() { 44 | def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.') 45 | def major = parsed[0].toInteger() 46 | def minor = parsed[1].toInteger() 47 | 48 | // Namespace support was added in 7.3.0 49 | return (major == 7 && minor >= 3) || major >= 8 50 | } 51 | 52 | android { 53 | if (supportsNamespace()) { 54 | namespace "com.unomed.reactnativematrixsdk" 55 | 56 | sourceSets { 57 | main { 58 | manifest.srcFile "src/main/AndroidManifestNew.xml" 59 | } 60 | } 61 | } 62 | 63 | ndkVersion getExtOrDefault("ndkVersion") 64 | compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") 65 | 66 | defaultConfig { 67 | minSdkVersion getExtOrIntegerDefault("minSdkVersion") 68 | targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") 69 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() 70 | consumerProguardFiles 'proguard-rules.pro' 71 | 72 | buildFeatures { 73 | prefab true 74 | } 75 | externalNativeBuild { 76 | cmake { 77 | arguments '-DANDROID_STL=c++_shared', 78 | '-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON' 79 | abiFilters (*reactNativeArchitectures()) 80 | } 81 | } 82 | ndk { 83 | abiFilters "arm64-v8a", "armeabi-v7a" 84 | } 85 | } 86 | 87 | externalNativeBuild { 88 | cmake { 89 | path "CMakeLists.txt" 90 | } 91 | } 92 | 93 | buildFeatures { 94 | buildConfig true 95 | } 96 | 97 | buildTypes { 98 | release { 99 | minifyEnabled false 100 | } 101 | } 102 | 103 | lintOptions { 104 | disable "GradleCompatible" 105 | } 106 | 107 | compileOptions { 108 | sourceCompatibility JavaVersion.VERSION_1_8 109 | targetCompatibility JavaVersion.VERSION_1_8 110 | } 111 | 112 | sourceSets { 113 | main { 114 | if (isNewArchitectureEnabled()) { 115 | java.srcDirs += [ 116 | "generated/java", 117 | "generated/jni" 118 | ] 119 | } 120 | } 121 | } 122 | } 123 | 124 | repositories { 125 | mavenCentral() 126 | google() 127 | } 128 | 129 | def kotlin_version = getExtOrDefault("kotlinVersion") 130 | 131 | dependencies { 132 | // For < 0.71, this will be from the local maven repo 133 | // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin 134 | //noinspection GradleDynamicVersion 135 | implementation "com.facebook.react:react-native:+" 136 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 137 | implementation "net.java.dev.jna:jna:5.17.0@aar" 138 | } 139 | 140 | if (isNewArchitectureEnabled()) { 141 | react { 142 | jsRootDir = file("../src/") 143 | libraryName = "ReactNativeMatrixSdk" 144 | codegenJavaPackageName = "com.unomed.reactnativematrixsdk" 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.application" 2 | apply plugin: "org.jetbrains.kotlin.android" 3 | apply plugin: "com.facebook.react" 4 | 5 | /** 6 | * This is the configuration block to customize your React Native Android app. 7 | * By default you don't need to apply any configuration, just uncomment the lines you need. 8 | */ 9 | react { 10 | /* Folders */ 11 | // The root of your project, i.e. where "package.json" lives. Default is '../..' 12 | // root = file("../../") 13 | // The folder where the react-native NPM package is. Default is ../../node_modules/react-native 14 | // reactNativeDir = file("../../node_modules/react-native") 15 | // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen 16 | // codegenDir = file("../../node_modules/@react-native/codegen") 17 | // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js 18 | // cliFile = file("../../node_modules/react-native/cli.js") 19 | 20 | /* Variants */ 21 | // The list of variants to that are debuggable. For those we're going to 22 | // skip the bundling of the JS bundle and the assets. By default is just 'debug'. 23 | // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. 24 | // debuggableVariants = ["liteDebug", "prodDebug"] 25 | 26 | /* Bundling */ 27 | // A list containing the node command and its flags. Default is just 'node'. 28 | // nodeExecutableAndArgs = ["node"] 29 | // 30 | // The command to run when bundling. By default is 'bundle' 31 | // bundleCommand = "ram-bundle" 32 | // 33 | // The path to the CLI configuration file. Default is empty. 34 | // bundleConfig = file(../rn-cli.config.js) 35 | // 36 | // The name of the generated asset file containing your JS bundle 37 | // bundleAssetName = "MyApplication.android.bundle" 38 | // 39 | // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' 40 | // entryFile = file("../js/MyApplication.android.js") 41 | // 42 | // A list of extra flags to pass to the 'bundle' commands. 43 | // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle 44 | // extraPackagerArgs = [] 45 | 46 | /* Hermes Commands */ 47 | // The hermes compiler command to run. By default it is 'hermesc' 48 | // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" 49 | // 50 | // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" 51 | // hermesFlags = ["-O", "-output-source-map"] 52 | 53 | /* Autolinking */ 54 | autolinkLibrariesWithApp() 55 | } 56 | 57 | /** 58 | * Set this to true to Run Proguard on Release builds to minify the Java bytecode. 59 | */ 60 | def enableProguardInReleaseBuilds = false 61 | 62 | /** 63 | * The preferred build flavor of JavaScriptCore (JSC) 64 | * 65 | * For example, to use the international variant, you can use: 66 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 67 | * 68 | * The international variant includes ICU i18n library and necessary data 69 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 70 | * give correct results when using with locales other than en-US. Note that 71 | * this variant is about 6MiB larger per architecture than default. 72 | */ 73 | def jscFlavor = 'org.webkit:android-jsc:+' 74 | 75 | android { 76 | ndkVersion rootProject.ext.ndkVersion 77 | buildToolsVersion rootProject.ext.buildToolsVersion 78 | compileSdk rootProject.ext.compileSdkVersion 79 | 80 | namespace "unomed.reactnativematrixsdk.example" 81 | defaultConfig { 82 | applicationId "unomed.reactnativematrixsdk.example" 83 | minSdkVersion rootProject.ext.minSdkVersion 84 | targetSdkVersion rootProject.ext.targetSdkVersion 85 | versionCode 1 86 | versionName "1.0" 87 | } 88 | signingConfigs { 89 | debug { 90 | storeFile file('debug.keystore') 91 | storePassword 'android' 92 | keyAlias 'androiddebugkey' 93 | keyPassword 'android' 94 | } 95 | } 96 | buildTypes { 97 | debug { 98 | signingConfig signingConfigs.debug 99 | } 100 | release { 101 | // Caution! In production, you need to generate your own keystore file. 102 | // see https://reactnative.dev/docs/signed-apk-android. 103 | signingConfig signingConfigs.debug 104 | minifyEnabled enableProguardInReleaseBuilds 105 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 106 | } 107 | } 108 | } 109 | 110 | dependencies { 111 | // The version of react-native is set by the React Native Gradle Plugin 112 | implementation("com.facebook.react:react-android") 113 | 114 | if (hermesEnabled.toBoolean()) { 115 | implementation("com.facebook.react:hermes-android") 116 | } else { 117 | implementation jscFlavor 118 | } 119 | } 120 | 121 | def isNewArchitectureEnabled() { 122 | return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" 123 | } 124 | 125 | if (isNewArchitectureEnabled()) { 126 | // Since our library doesn't invoke codegen automatically we need to do it here. 127 | tasks.register('invokeLibraryCodegen', Exec) { 128 | workingDir "$rootDir/../../" 129 | commandLine "npx", "bob", "build", "--target", "codegen" 130 | } 131 | preBuild.dependsOn invokeLibraryCodegen 132 | } -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are always welcome, no matter how large or small. 4 | 5 | 6 | ## Development workflow 7 | 8 | This project is a monorepo managed using [Yarn workspaces]. It contains the following packages: 9 | 10 | - The library package in the root directory. 11 | - An example app in the `example/` directory. 12 | 13 | To get started with the project, run `yarn` in the root directory to install the required 14 | dependencies for each package: 15 | 16 | ```sh 17 | yarn 18 | ``` 19 | 20 | > Since the project relies on Yarn workspaces, you cannot use [`npm`] for development. 21 | 22 | The [example app] demonstrates usage of the library. You need to run it to test any changes you 23 | make. 24 | 25 | It is configured to use the local version of the library, so any changes you make to the library's 26 | source code will be reflected in the example app. Changes to the library's JavaScript code will be 27 | reflected in the example app without a rebuild, but native code changes will require a rebuild of 28 | the example app. 29 | 30 | If you want to use Android Studio or Xcode to edit the native code, you can open the 31 | `example/android` or `example/ios` directories respectively in those editors. To edit the 32 | Objective-C or Swift files, open `example/ios/MatrixSdkExample.xcworkspace` in Xcode and find the 33 | source files at `Pods > Development Pods > react-native-matrix-sdk`. 34 | 35 | To edit the Java or Kotlin files, open `example/android` in Android studio and find the source 36 | files at `react-native-matrix-sdk` under `Android`. 37 | 38 | You can use various commands from the root directory to work with the project. 39 | 40 | To start the packager: 41 | 42 | ```sh 43 | yarn example start 44 | ``` 45 | 46 | To run the example app on Android: 47 | 48 | ```sh 49 | yarn example android 50 | ``` 51 | 52 | To run the example app on iOS: 53 | 54 | ```sh 55 | yarn example ios 56 | ``` 57 | 58 | To confirm that the app is running with the new architecture, you can check the Metro logs for a 59 | message like this: 60 | 61 | ```sh 62 | Running "MatrixSdkExample" with {"fabric":true,"initialProps":{"concurrentRoot":true},"rootTag":1} 63 | ``` 64 | 65 | Note the `"fabric":true` and `"concurrentRoot":true` properties. 66 | 67 | Make sure your code passes TypeScript and ESLint. Run the following to verify: 68 | 69 | ```sh 70 | yarn typecheck 71 | yarn lint 72 | ``` 73 | 74 | To fix formatting errors, run the following: 75 | 76 | ```sh 77 | yarn lint --fix 78 | ``` 79 | 80 | Remember to add tests for your change if possible. Run the unit tests by: 81 | 82 | ```sh 83 | yarn test 84 | ``` 85 | 86 | 87 | ### Regenerating the module 88 | 89 | To regenerate the Turbo Module, run: 90 | 91 | ```sh 92 | yarn generate 93 | ``` 94 | 95 | 96 | ### Commit message convention 97 | 98 | We follow the [conventional commits specification] for our commit messages: 99 | 100 | - `fix`: bug fixes, e.g. fix crash due to deprecated method. 101 | - `feat`: new features, e.g. add new method to the module. 102 | - `refactor`: code refactor, e.g. migrate from class components to hooks. 103 | - `docs`: changes to documentation, e.g. add usage example for the module. 104 | - `test`: adding or updating tests, e.g. add integration tests using detox. 105 | - `chore`: tooling changes, e.g. change CI config. 106 | 107 | Our pre-commit hooks verify that your commit message matches this format when committing. 108 | 109 | 110 | ### Linting and tests 111 | 112 | We use [TypeScript] for type checking, [ESLint] with [Prettier] for linting and formatting the 113 | code, and [Jest] for testing. 114 | 115 | Our pre-commit hooks verify that the linter and tests pass when committing. To install the hooks 116 | run: 117 | 118 | ```sh 119 | yarn run lefthook install 120 | ``` 121 | 122 | 123 | ### Publishing to npm 124 | 125 | We use [release-it] to make it easier to publish new versions. It handles common tasks like bumping 126 | the version based on semver, creating tags and releases etc. 127 | 128 | To publish new versions, run the following: 129 | 130 | ```sh 131 | yarn release 132 | ``` 133 | 134 | 135 | ### Scripts 136 | 137 | The `package.json` file contains various scripts for common tasks: 138 | 139 | - `yarn`: setup project by installing dependencies. 140 | - `yarn typecheck`: type-check files with TypeScript. 141 | - `yarn lint`: lint files with ESLint. 142 | - `yarn test`: run unit tests with Jest. 143 | - `yarn example start`: start the Metro server for the example app. 144 | - `yarn example android`: run the example app on Android. 145 | - `yarn example ios`: run the example app on iOS. 146 | 147 | 148 | ### Sending a pull request 149 | 150 | When you're sending a pull request: 151 | 152 | - Prefer small pull requests focused on one change. 153 | - Verify that linters and tests are passing. 154 | - Review the documentation to make sure it looks good. 155 | - Follow the pull request template when opening a pull request. 156 | - For pull requests that change the API or implementation, discuss with maintainers first by opening an issue. 157 | 158 | 159 | [conventional commits specification]: https://www.conventionalcommits.org/en 160 | [ESLint]: https://eslint.org/ 161 | [example app]: /example/ 162 | [Jest]: https://jestjs.io/ 163 | [matrix-rust-components-kotlin]: https://github.com/matrix-org/matrix-rust-components-kotlin 164 | [matrix-rust-components-swift]: https://github.com/matrix-org/matrix-rust-components-swift 165 | [matrix-rust-sdk]: https://github.com/matrix-org/matrix-rust-sdk 166 | [`npm`]: https://github.com/npm/cli 167 | [Prettier]: https://prettier.io/ 168 | [release-it]: https://github.com/release-it/release-it 169 | [TypeScript]: https://www.typescriptlang.org/ 170 | [Yarn workspaces]: https://yarnpkg.com/features/workspaces 171 | -------------------------------------------------------------------------------- /src/generated/matrix_sdk_common.ts: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. 2 | // Trust me, you don't want to mess with it! 3 | import nativeModule, { 4 | type UniffiRustFutureContinuationCallback, 5 | type UniffiForeignFuture, 6 | type UniffiForeignFutureStructU8, 7 | type UniffiForeignFutureCompleteU8, 8 | type UniffiForeignFutureStructI8, 9 | type UniffiForeignFutureCompleteI8, 10 | type UniffiForeignFutureStructU16, 11 | type UniffiForeignFutureCompleteU16, 12 | type UniffiForeignFutureStructI16, 13 | type UniffiForeignFutureCompleteI16, 14 | type UniffiForeignFutureStructU32, 15 | type UniffiForeignFutureCompleteU32, 16 | type UniffiForeignFutureStructI32, 17 | type UniffiForeignFutureCompleteI32, 18 | type UniffiForeignFutureStructU64, 19 | type UniffiForeignFutureCompleteU64, 20 | type UniffiForeignFutureStructI64, 21 | type UniffiForeignFutureCompleteI64, 22 | type UniffiForeignFutureStructF32, 23 | type UniffiForeignFutureCompleteF32, 24 | type UniffiForeignFutureStructF64, 25 | type UniffiForeignFutureCompleteF64, 26 | type UniffiForeignFutureStructPointer, 27 | type UniffiForeignFutureCompletePointer, 28 | type UniffiForeignFutureStructRustBuffer, 29 | type UniffiForeignFutureCompleteRustBuffer, 30 | type UniffiForeignFutureStructVoid, 31 | type UniffiForeignFutureCompleteVoid, 32 | } from './matrix_sdk_common-ffi'; 33 | import { 34 | type UniffiByteArray, 35 | AbstractFfiConverterByteArray, 36 | FfiConverterInt32, 37 | RustBuffer, 38 | UniffiInternalError, 39 | UniffiRustCaller, 40 | uniffiCreateFfiConverterString, 41 | } from 'uniffi-bindgen-react-native'; 42 | 43 | // Get converters from the other files, if any. 44 | const uniffiCaller = new UniffiRustCaller(() => ({ code: 0 })); 45 | 46 | const uniffiIsDebug = 47 | // @ts-ignore -- The process global might not be defined 48 | typeof process !== 'object' || 49 | // @ts-ignore -- The process global might not be defined 50 | process?.env?.NODE_ENV !== 'production' || 51 | false; 52 | // Public interface members begin here. 53 | 54 | const stringConverter = { 55 | stringToBytes: (s: string) => 56 | uniffiCaller.rustCall((status) => 57 | nativeModule().ubrn_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 58 | s, 59 | status 60 | ) 61 | ), 62 | bytesToString: (ab: UniffiByteArray) => 63 | uniffiCaller.rustCall((status) => 64 | nativeModule().ubrn_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 65 | ab, 66 | status 67 | ) 68 | ), 69 | stringByteLength: (s: string) => 70 | uniffiCaller.rustCall((status) => 71 | nativeModule().ubrn_uniffi_internal_fn_func_ffi__string_to_byte_length( 72 | s, 73 | status 74 | ) 75 | ), 76 | }; 77 | const FfiConverterString = uniffiCreateFfiConverterString(stringConverter); 78 | 79 | /** 80 | * A machine-readable representation of the authenticity for a `ShieldState`. 81 | */ 82 | export enum ShieldStateCode { 83 | /** 84 | * Not enough information available to check the authenticity. 85 | */ 86 | AuthenticityNotGuaranteed, 87 | /** 88 | * The sending device isn't yet known by the Client. 89 | */ 90 | UnknownDevice, 91 | /** 92 | * The sending device hasn't been verified by the sender. 93 | */ 94 | UnsignedDevice, 95 | /** 96 | * The sender hasn't been verified by the Client's user. 97 | */ 98 | UnverifiedIdentity, 99 | /** 100 | * An unencrypted event in an encrypted room. 101 | */ 102 | SentInClear, 103 | /** 104 | * The sender was previously verified but changed their identity. 105 | */ 106 | VerificationViolation, 107 | /** 108 | * The `sender` field on the event does not match the owner of the device 109 | * that established the Megolm session. 110 | */ 111 | MismatchedSender, 112 | } 113 | 114 | const FfiConverterTypeShieldStateCode = (() => { 115 | const ordinalConverter = FfiConverterInt32; 116 | type TypeName = ShieldStateCode; 117 | class FFIConverter extends AbstractFfiConverterByteArray { 118 | read(from: RustBuffer): TypeName { 119 | switch (ordinalConverter.read(from)) { 120 | case 1: 121 | return ShieldStateCode.AuthenticityNotGuaranteed; 122 | case 2: 123 | return ShieldStateCode.UnknownDevice; 124 | case 3: 125 | return ShieldStateCode.UnsignedDevice; 126 | case 4: 127 | return ShieldStateCode.UnverifiedIdentity; 128 | case 5: 129 | return ShieldStateCode.SentInClear; 130 | case 6: 131 | return ShieldStateCode.VerificationViolation; 132 | case 7: 133 | return ShieldStateCode.MismatchedSender; 134 | default: 135 | throw new UniffiInternalError.UnexpectedEnumCase(); 136 | } 137 | } 138 | write(value: TypeName, into: RustBuffer): void { 139 | switch (value) { 140 | case ShieldStateCode.AuthenticityNotGuaranteed: 141 | return ordinalConverter.write(1, into); 142 | case ShieldStateCode.UnknownDevice: 143 | return ordinalConverter.write(2, into); 144 | case ShieldStateCode.UnsignedDevice: 145 | return ordinalConverter.write(3, into); 146 | case ShieldStateCode.UnverifiedIdentity: 147 | return ordinalConverter.write(4, into); 148 | case ShieldStateCode.SentInClear: 149 | return ordinalConverter.write(5, into); 150 | case ShieldStateCode.VerificationViolation: 151 | return ordinalConverter.write(6, into); 152 | case ShieldStateCode.MismatchedSender: 153 | return ordinalConverter.write(7, into); 154 | } 155 | } 156 | allocationSize(value: TypeName): number { 157 | return ordinalConverter.allocationSize(0); 158 | } 159 | } 160 | return new FFIConverter(); 161 | })(); 162 | 163 | /** 164 | * This should be called before anything else. 165 | * 166 | * It is likely that this is being done for you by the library's `index.ts`. 167 | * 168 | * It checks versions of uniffi between when the Rust scaffolding was generated 169 | * and when the bindings were generated. 170 | * 171 | * It also initializes the machinery to enable Rust to talk back to Javascript. 172 | */ 173 | function uniffiEnsureInitialized() { 174 | // Get the bindings contract version from our ComponentInterface 175 | const bindingsContractVersion = 29; 176 | // Get the scaffolding contract version by calling the into the dylib 177 | const scaffoldingContractVersion = 178 | nativeModule().ubrn_ffi_matrix_sdk_common_uniffi_contract_version(); 179 | if (bindingsContractVersion !== scaffoldingContractVersion) { 180 | throw new UniffiInternalError.ContractVersionMismatch( 181 | scaffoldingContractVersion, 182 | bindingsContractVersion 183 | ); 184 | } 185 | } 186 | 187 | export default Object.freeze({ 188 | initialize: uniffiEnsureInitialized, 189 | converters: { 190 | FfiConverterTypeShieldStateCode, 191 | }, 192 | }); 193 | -------------------------------------------------------------------------------- /src/generated/matrix_sdk_ui-ffi.ts: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. 2 | // Trust me, you don't want to mess with it! 3 | 4 | import { 5 | type StructuralEquality as UniffiStructuralEquality, 6 | type UniffiForeignFuture as RuntimeUniffiForeignFuture, 7 | type UniffiRustCallStatus, 8 | type UniffiRustArcPtr, 9 | type UniffiRustFutureContinuationCallback as RuntimeUniffiRustFutureContinuationCallback, 10 | type UniffiResult, 11 | } from 'uniffi-bindgen-react-native'; 12 | 13 | interface NativeModuleInterface { 14 | ubrn_uniffi_internal_fn_func_ffi__string_to_byte_length( 15 | string: string, 16 | uniffi_out_err: UniffiRustCallStatus 17 | ): number; 18 | ubrn_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 19 | string: string, 20 | uniffi_out_err: UniffiRustCallStatus 21 | ): Uint8Array; 22 | ubrn_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 23 | buffer: Uint8Array, 24 | uniffi_out_err: UniffiRustCallStatus 25 | ): string; 26 | ubrn_ffi_matrix_sdk_ui_uniffi_contract_version(): number; 27 | } 28 | 29 | // Casting globalThis to any allows us to look for `NativeMatrixSdkUi` 30 | // if it was added via JSI. 31 | // 32 | // We use a getter here rather than simply `globalThis.NativeMatrixSdkUi` so that 33 | // if/when the startup sequence isn't just so, an empty value isn't inadvertantly cached. 34 | const getter: () => NativeModuleInterface = () => 35 | (globalThis as any).NativeMatrixSdkUi; 36 | export default getter; 37 | 38 | // Structs and function types for calling back into Typescript from Rust. 39 | export type UniffiRustFutureContinuationCallback = ( 40 | data: bigint, 41 | pollResult: number 42 | ) => void; 43 | type UniffiForeignFutureFree = (handle: bigint) => void; 44 | type UniffiCallbackInterfaceFree = (handle: bigint) => void; 45 | export type UniffiForeignFuture = { 46 | handle: bigint; 47 | free: UniffiForeignFutureFree; 48 | }; 49 | export type UniffiForeignFutureStructU8 = { 50 | returnValue: number; 51 | callStatus: UniffiRustCallStatus; 52 | }; 53 | export type UniffiForeignFutureCompleteU8 = ( 54 | callbackData: bigint, 55 | result: UniffiForeignFutureStructU8 56 | ) => void; 57 | export type UniffiForeignFutureStructI8 = { 58 | returnValue: number; 59 | callStatus: UniffiRustCallStatus; 60 | }; 61 | export type UniffiForeignFutureCompleteI8 = ( 62 | callbackData: bigint, 63 | result: UniffiForeignFutureStructI8 64 | ) => void; 65 | export type UniffiForeignFutureStructU16 = { 66 | returnValue: number; 67 | callStatus: UniffiRustCallStatus; 68 | }; 69 | export type UniffiForeignFutureCompleteU16 = ( 70 | callbackData: bigint, 71 | result: UniffiForeignFutureStructU16 72 | ) => void; 73 | export type UniffiForeignFutureStructI16 = { 74 | returnValue: number; 75 | callStatus: UniffiRustCallStatus; 76 | }; 77 | export type UniffiForeignFutureCompleteI16 = ( 78 | callbackData: bigint, 79 | result: UniffiForeignFutureStructI16 80 | ) => void; 81 | export type UniffiForeignFutureStructU32 = { 82 | returnValue: number; 83 | callStatus: UniffiRustCallStatus; 84 | }; 85 | export type UniffiForeignFutureCompleteU32 = ( 86 | callbackData: bigint, 87 | result: UniffiForeignFutureStructU32 88 | ) => void; 89 | export type UniffiForeignFutureStructI32 = { 90 | returnValue: number; 91 | callStatus: UniffiRustCallStatus; 92 | }; 93 | export type UniffiForeignFutureCompleteI32 = ( 94 | callbackData: bigint, 95 | result: UniffiForeignFutureStructI32 96 | ) => void; 97 | export type UniffiForeignFutureStructU64 = { 98 | returnValue: bigint; 99 | callStatus: UniffiRustCallStatus; 100 | }; 101 | export type UniffiForeignFutureCompleteU64 = ( 102 | callbackData: bigint, 103 | result: UniffiForeignFutureStructU64 104 | ) => void; 105 | export type UniffiForeignFutureStructI64 = { 106 | returnValue: bigint; 107 | callStatus: UniffiRustCallStatus; 108 | }; 109 | export type UniffiForeignFutureCompleteI64 = ( 110 | callbackData: bigint, 111 | result: UniffiForeignFutureStructI64 112 | ) => void; 113 | export type UniffiForeignFutureStructF32 = { 114 | returnValue: number; 115 | callStatus: UniffiRustCallStatus; 116 | }; 117 | export type UniffiForeignFutureCompleteF32 = ( 118 | callbackData: bigint, 119 | result: UniffiForeignFutureStructF32 120 | ) => void; 121 | export type UniffiForeignFutureStructF64 = { 122 | returnValue: number; 123 | callStatus: UniffiRustCallStatus; 124 | }; 125 | export type UniffiForeignFutureCompleteF64 = ( 126 | callbackData: bigint, 127 | result: UniffiForeignFutureStructF64 128 | ) => void; 129 | export type UniffiForeignFutureStructPointer = { 130 | returnValue: bigint; 131 | callStatus: UniffiRustCallStatus; 132 | }; 133 | export type UniffiForeignFutureCompletePointer = ( 134 | callbackData: bigint, 135 | result: UniffiForeignFutureStructPointer 136 | ) => void; 137 | export type UniffiForeignFutureStructRustBuffer = { 138 | returnValue: Uint8Array; 139 | callStatus: UniffiRustCallStatus; 140 | }; 141 | export type UniffiForeignFutureCompleteRustBuffer = ( 142 | callbackData: bigint, 143 | result: UniffiForeignFutureStructRustBuffer 144 | ) => void; 145 | export type UniffiForeignFutureStructVoid = { 146 | callStatus: UniffiRustCallStatus; 147 | }; 148 | export type UniffiForeignFutureCompleteVoid = ( 149 | callbackData: bigint, 150 | result: UniffiForeignFutureStructVoid 151 | ) => void; 152 | 153 | // UniffiRustFutureContinuationCallback is generated as part of the component interface's 154 | // ffi_definitions. However, we need it in the runtime. 155 | // We could: 156 | // (a) do some complicated template logic to ensure the declaration is not generated here (possible) 157 | // (b) import the generated declaration into the runtime (m a y b e) or… 158 | // (c) generate the declaration anyway, and use a different declaration in the runtime. 159 | // 160 | // We chose (c) here as the simplest. In addition, we perform a compile time check that 161 | // the two versions of `UniffiRustFutureContinuationCallback` are structurally equivalent. 162 | // 163 | // If you see the error: 164 | // ``` 165 | // Type 'true' is not assignable to type 'false'.(2322) 166 | // ``` 167 | // Then a new version of uniffi has changed the signature of the callback. Most likely, code in 168 | // `typescript/src/async-rust-call.ts` will need to be changed. 169 | // 170 | // If you see the error: 171 | // ``` 172 | // Cannot find name 'UniffiRustFutureContinuationCallback'. Did you mean 'RuntimeUniffiRustFutureContinuationCallback'?(2552) 173 | // ``` 174 | // then you may not be using callbacks or promises, and uniffi is now not generating Futures and callbacks. 175 | // You should not generate this if that is the case. 176 | // 177 | // ('You' being the bindings generator maintainer). 178 | const isRustFutureContinuationCallbackTypeCompatible: UniffiStructuralEquality< 179 | RuntimeUniffiRustFutureContinuationCallback, 180 | UniffiRustFutureContinuationCallback 181 | > = true; 182 | const isUniffiForeignFutureTypeCompatible: UniffiStructuralEquality< 183 | RuntimeUniffiForeignFuture, 184 | UniffiForeignFuture 185 | > = true; 186 | -------------------------------------------------------------------------------- /src/generated/matrix_sdk_base-ffi.ts: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. 2 | // Trust me, you don't want to mess with it! 3 | 4 | import { 5 | type StructuralEquality as UniffiStructuralEquality, 6 | type UniffiForeignFuture as RuntimeUniffiForeignFuture, 7 | type UniffiRustCallStatus, 8 | type UniffiRustArcPtr, 9 | type UniffiRustFutureContinuationCallback as RuntimeUniffiRustFutureContinuationCallback, 10 | type UniffiResult, 11 | } from 'uniffi-bindgen-react-native'; 12 | 13 | interface NativeModuleInterface { 14 | ubrn_uniffi_internal_fn_func_ffi__string_to_byte_length( 15 | string: string, 16 | uniffi_out_err: UniffiRustCallStatus 17 | ): number; 18 | ubrn_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 19 | string: string, 20 | uniffi_out_err: UniffiRustCallStatus 21 | ): Uint8Array; 22 | ubrn_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 23 | buffer: Uint8Array, 24 | uniffi_out_err: UniffiRustCallStatus 25 | ): string; 26 | ubrn_ffi_matrix_sdk_base_uniffi_contract_version(): number; 27 | } 28 | 29 | // Casting globalThis to any allows us to look for `NativeMatrixSdkBase` 30 | // if it was added via JSI. 31 | // 32 | // We use a getter here rather than simply `globalThis.NativeMatrixSdkBase` so that 33 | // if/when the startup sequence isn't just so, an empty value isn't inadvertantly cached. 34 | const getter: () => NativeModuleInterface = () => 35 | (globalThis as any).NativeMatrixSdkBase; 36 | export default getter; 37 | 38 | // Structs and function types for calling back into Typescript from Rust. 39 | export type UniffiRustFutureContinuationCallback = ( 40 | data: bigint, 41 | pollResult: number 42 | ) => void; 43 | type UniffiForeignFutureFree = (handle: bigint) => void; 44 | type UniffiCallbackInterfaceFree = (handle: bigint) => void; 45 | export type UniffiForeignFuture = { 46 | handle: bigint; 47 | free: UniffiForeignFutureFree; 48 | }; 49 | export type UniffiForeignFutureStructU8 = { 50 | returnValue: number; 51 | callStatus: UniffiRustCallStatus; 52 | }; 53 | export type UniffiForeignFutureCompleteU8 = ( 54 | callbackData: bigint, 55 | result: UniffiForeignFutureStructU8 56 | ) => void; 57 | export type UniffiForeignFutureStructI8 = { 58 | returnValue: number; 59 | callStatus: UniffiRustCallStatus; 60 | }; 61 | export type UniffiForeignFutureCompleteI8 = ( 62 | callbackData: bigint, 63 | result: UniffiForeignFutureStructI8 64 | ) => void; 65 | export type UniffiForeignFutureStructU16 = { 66 | returnValue: number; 67 | callStatus: UniffiRustCallStatus; 68 | }; 69 | export type UniffiForeignFutureCompleteU16 = ( 70 | callbackData: bigint, 71 | result: UniffiForeignFutureStructU16 72 | ) => void; 73 | export type UniffiForeignFutureStructI16 = { 74 | returnValue: number; 75 | callStatus: UniffiRustCallStatus; 76 | }; 77 | export type UniffiForeignFutureCompleteI16 = ( 78 | callbackData: bigint, 79 | result: UniffiForeignFutureStructI16 80 | ) => void; 81 | export type UniffiForeignFutureStructU32 = { 82 | returnValue: number; 83 | callStatus: UniffiRustCallStatus; 84 | }; 85 | export type UniffiForeignFutureCompleteU32 = ( 86 | callbackData: bigint, 87 | result: UniffiForeignFutureStructU32 88 | ) => void; 89 | export type UniffiForeignFutureStructI32 = { 90 | returnValue: number; 91 | callStatus: UniffiRustCallStatus; 92 | }; 93 | export type UniffiForeignFutureCompleteI32 = ( 94 | callbackData: bigint, 95 | result: UniffiForeignFutureStructI32 96 | ) => void; 97 | export type UniffiForeignFutureStructU64 = { 98 | returnValue: bigint; 99 | callStatus: UniffiRustCallStatus; 100 | }; 101 | export type UniffiForeignFutureCompleteU64 = ( 102 | callbackData: bigint, 103 | result: UniffiForeignFutureStructU64 104 | ) => void; 105 | export type UniffiForeignFutureStructI64 = { 106 | returnValue: bigint; 107 | callStatus: UniffiRustCallStatus; 108 | }; 109 | export type UniffiForeignFutureCompleteI64 = ( 110 | callbackData: bigint, 111 | result: UniffiForeignFutureStructI64 112 | ) => void; 113 | export type UniffiForeignFutureStructF32 = { 114 | returnValue: number; 115 | callStatus: UniffiRustCallStatus; 116 | }; 117 | export type UniffiForeignFutureCompleteF32 = ( 118 | callbackData: bigint, 119 | result: UniffiForeignFutureStructF32 120 | ) => void; 121 | export type UniffiForeignFutureStructF64 = { 122 | returnValue: number; 123 | callStatus: UniffiRustCallStatus; 124 | }; 125 | export type UniffiForeignFutureCompleteF64 = ( 126 | callbackData: bigint, 127 | result: UniffiForeignFutureStructF64 128 | ) => void; 129 | export type UniffiForeignFutureStructPointer = { 130 | returnValue: bigint; 131 | callStatus: UniffiRustCallStatus; 132 | }; 133 | export type UniffiForeignFutureCompletePointer = ( 134 | callbackData: bigint, 135 | result: UniffiForeignFutureStructPointer 136 | ) => void; 137 | export type UniffiForeignFutureStructRustBuffer = { 138 | returnValue: Uint8Array; 139 | callStatus: UniffiRustCallStatus; 140 | }; 141 | export type UniffiForeignFutureCompleteRustBuffer = ( 142 | callbackData: bigint, 143 | result: UniffiForeignFutureStructRustBuffer 144 | ) => void; 145 | export type UniffiForeignFutureStructVoid = { 146 | callStatus: UniffiRustCallStatus; 147 | }; 148 | export type UniffiForeignFutureCompleteVoid = ( 149 | callbackData: bigint, 150 | result: UniffiForeignFutureStructVoid 151 | ) => void; 152 | 153 | // UniffiRustFutureContinuationCallback is generated as part of the component interface's 154 | // ffi_definitions. However, we need it in the runtime. 155 | // We could: 156 | // (a) do some complicated template logic to ensure the declaration is not generated here (possible) 157 | // (b) import the generated declaration into the runtime (m a y b e) or… 158 | // (c) generate the declaration anyway, and use a different declaration in the runtime. 159 | // 160 | // We chose (c) here as the simplest. In addition, we perform a compile time check that 161 | // the two versions of `UniffiRustFutureContinuationCallback` are structurally equivalent. 162 | // 163 | // If you see the error: 164 | // ``` 165 | // Type 'true' is not assignable to type 'false'.(2322) 166 | // ``` 167 | // Then a new version of uniffi has changed the signature of the callback. Most likely, code in 168 | // `typescript/src/async-rust-call.ts` will need to be changed. 169 | // 170 | // If you see the error: 171 | // ``` 172 | // Cannot find name 'UniffiRustFutureContinuationCallback'. Did you mean 'RuntimeUniffiRustFutureContinuationCallback'?(2552) 173 | // ``` 174 | // then you may not be using callbacks or promises, and uniffi is now not generating Futures and callbacks. 175 | // You should not generate this if that is the case. 176 | // 177 | // ('You' being the bindings generator maintainer). 178 | const isRustFutureContinuationCallbackTypeCompatible: UniffiStructuralEquality< 179 | RuntimeUniffiRustFutureContinuationCallback, 180 | UniffiRustFutureContinuationCallback 181 | > = true; 182 | const isUniffiForeignFutureTypeCompatible: UniffiStructuralEquality< 183 | RuntimeUniffiForeignFuture, 184 | UniffiForeignFuture 185 | > = true; 186 | -------------------------------------------------------------------------------- /src/generated/matrix_sdk_common-ffi.ts: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. 2 | // Trust me, you don't want to mess with it! 3 | 4 | import { 5 | type StructuralEquality as UniffiStructuralEquality, 6 | type UniffiForeignFuture as RuntimeUniffiForeignFuture, 7 | type UniffiRustCallStatus, 8 | type UniffiRustArcPtr, 9 | type UniffiRustFutureContinuationCallback as RuntimeUniffiRustFutureContinuationCallback, 10 | type UniffiResult, 11 | } from 'uniffi-bindgen-react-native'; 12 | 13 | interface NativeModuleInterface { 14 | ubrn_uniffi_internal_fn_func_ffi__string_to_byte_length( 15 | string: string, 16 | uniffi_out_err: UniffiRustCallStatus 17 | ): number; 18 | ubrn_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 19 | string: string, 20 | uniffi_out_err: UniffiRustCallStatus 21 | ): Uint8Array; 22 | ubrn_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 23 | buffer: Uint8Array, 24 | uniffi_out_err: UniffiRustCallStatus 25 | ): string; 26 | ubrn_ffi_matrix_sdk_common_uniffi_contract_version(): number; 27 | } 28 | 29 | // Casting globalThis to any allows us to look for `NativeMatrixSdkCommon` 30 | // if it was added via JSI. 31 | // 32 | // We use a getter here rather than simply `globalThis.NativeMatrixSdkCommon` so that 33 | // if/when the startup sequence isn't just so, an empty value isn't inadvertantly cached. 34 | const getter: () => NativeModuleInterface = () => 35 | (globalThis as any).NativeMatrixSdkCommon; 36 | export default getter; 37 | 38 | // Structs and function types for calling back into Typescript from Rust. 39 | export type UniffiRustFutureContinuationCallback = ( 40 | data: bigint, 41 | pollResult: number 42 | ) => void; 43 | type UniffiForeignFutureFree = (handle: bigint) => void; 44 | type UniffiCallbackInterfaceFree = (handle: bigint) => void; 45 | export type UniffiForeignFuture = { 46 | handle: bigint; 47 | free: UniffiForeignFutureFree; 48 | }; 49 | export type UniffiForeignFutureStructU8 = { 50 | returnValue: number; 51 | callStatus: UniffiRustCallStatus; 52 | }; 53 | export type UniffiForeignFutureCompleteU8 = ( 54 | callbackData: bigint, 55 | result: UniffiForeignFutureStructU8 56 | ) => void; 57 | export type UniffiForeignFutureStructI8 = { 58 | returnValue: number; 59 | callStatus: UniffiRustCallStatus; 60 | }; 61 | export type UniffiForeignFutureCompleteI8 = ( 62 | callbackData: bigint, 63 | result: UniffiForeignFutureStructI8 64 | ) => void; 65 | export type UniffiForeignFutureStructU16 = { 66 | returnValue: number; 67 | callStatus: UniffiRustCallStatus; 68 | }; 69 | export type UniffiForeignFutureCompleteU16 = ( 70 | callbackData: bigint, 71 | result: UniffiForeignFutureStructU16 72 | ) => void; 73 | export type UniffiForeignFutureStructI16 = { 74 | returnValue: number; 75 | callStatus: UniffiRustCallStatus; 76 | }; 77 | export type UniffiForeignFutureCompleteI16 = ( 78 | callbackData: bigint, 79 | result: UniffiForeignFutureStructI16 80 | ) => void; 81 | export type UniffiForeignFutureStructU32 = { 82 | returnValue: number; 83 | callStatus: UniffiRustCallStatus; 84 | }; 85 | export type UniffiForeignFutureCompleteU32 = ( 86 | callbackData: bigint, 87 | result: UniffiForeignFutureStructU32 88 | ) => void; 89 | export type UniffiForeignFutureStructI32 = { 90 | returnValue: number; 91 | callStatus: UniffiRustCallStatus; 92 | }; 93 | export type UniffiForeignFutureCompleteI32 = ( 94 | callbackData: bigint, 95 | result: UniffiForeignFutureStructI32 96 | ) => void; 97 | export type UniffiForeignFutureStructU64 = { 98 | returnValue: bigint; 99 | callStatus: UniffiRustCallStatus; 100 | }; 101 | export type UniffiForeignFutureCompleteU64 = ( 102 | callbackData: bigint, 103 | result: UniffiForeignFutureStructU64 104 | ) => void; 105 | export type UniffiForeignFutureStructI64 = { 106 | returnValue: bigint; 107 | callStatus: UniffiRustCallStatus; 108 | }; 109 | export type UniffiForeignFutureCompleteI64 = ( 110 | callbackData: bigint, 111 | result: UniffiForeignFutureStructI64 112 | ) => void; 113 | export type UniffiForeignFutureStructF32 = { 114 | returnValue: number; 115 | callStatus: UniffiRustCallStatus; 116 | }; 117 | export type UniffiForeignFutureCompleteF32 = ( 118 | callbackData: bigint, 119 | result: UniffiForeignFutureStructF32 120 | ) => void; 121 | export type UniffiForeignFutureStructF64 = { 122 | returnValue: number; 123 | callStatus: UniffiRustCallStatus; 124 | }; 125 | export type UniffiForeignFutureCompleteF64 = ( 126 | callbackData: bigint, 127 | result: UniffiForeignFutureStructF64 128 | ) => void; 129 | export type UniffiForeignFutureStructPointer = { 130 | returnValue: bigint; 131 | callStatus: UniffiRustCallStatus; 132 | }; 133 | export type UniffiForeignFutureCompletePointer = ( 134 | callbackData: bigint, 135 | result: UniffiForeignFutureStructPointer 136 | ) => void; 137 | export type UniffiForeignFutureStructRustBuffer = { 138 | returnValue: Uint8Array; 139 | callStatus: UniffiRustCallStatus; 140 | }; 141 | export type UniffiForeignFutureCompleteRustBuffer = ( 142 | callbackData: bigint, 143 | result: UniffiForeignFutureStructRustBuffer 144 | ) => void; 145 | export type UniffiForeignFutureStructVoid = { 146 | callStatus: UniffiRustCallStatus; 147 | }; 148 | export type UniffiForeignFutureCompleteVoid = ( 149 | callbackData: bigint, 150 | result: UniffiForeignFutureStructVoid 151 | ) => void; 152 | 153 | // UniffiRustFutureContinuationCallback is generated as part of the component interface's 154 | // ffi_definitions. However, we need it in the runtime. 155 | // We could: 156 | // (a) do some complicated template logic to ensure the declaration is not generated here (possible) 157 | // (b) import the generated declaration into the runtime (m a y b e) or… 158 | // (c) generate the declaration anyway, and use a different declaration in the runtime. 159 | // 160 | // We chose (c) here as the simplest. In addition, we perform a compile time check that 161 | // the two versions of `UniffiRustFutureContinuationCallback` are structurally equivalent. 162 | // 163 | // If you see the error: 164 | // ``` 165 | // Type 'true' is not assignable to type 'false'.(2322) 166 | // ``` 167 | // Then a new version of uniffi has changed the signature of the callback. Most likely, code in 168 | // `typescript/src/async-rust-call.ts` will need to be changed. 169 | // 170 | // If you see the error: 171 | // ``` 172 | // Cannot find name 'UniffiRustFutureContinuationCallback'. Did you mean 'RuntimeUniffiRustFutureContinuationCallback'?(2552) 173 | // ``` 174 | // then you may not be using callbacks or promises, and uniffi is now not generating Futures and callbacks. 175 | // You should not generate this if that is the case. 176 | // 177 | // ('You' being the bindings generator maintainer). 178 | const isRustFutureContinuationCallbackTypeCompatible: UniffiStructuralEquality< 179 | RuntimeUniffiRustFutureContinuationCallback, 180 | UniffiRustFutureContinuationCallback 181 | > = true; 182 | const isUniffiForeignFutureTypeCompatible: UniffiStructuralEquality< 183 | RuntimeUniffiForeignFuture, 184 | UniffiForeignFuture 185 | > = true; 186 | -------------------------------------------------------------------------------- /src/generated/matrix_sdk_crypto-ffi.ts: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. 2 | // Trust me, you don't want to mess with it! 3 | 4 | import { 5 | type StructuralEquality as UniffiStructuralEquality, 6 | type UniffiForeignFuture as RuntimeUniffiForeignFuture, 7 | type UniffiRustCallStatus, 8 | type UniffiRustArcPtr, 9 | type UniffiRustFutureContinuationCallback as RuntimeUniffiRustFutureContinuationCallback, 10 | type UniffiResult, 11 | } from 'uniffi-bindgen-react-native'; 12 | 13 | interface NativeModuleInterface { 14 | ubrn_uniffi_internal_fn_func_ffi__string_to_byte_length( 15 | string: string, 16 | uniffi_out_err: UniffiRustCallStatus 17 | ): number; 18 | ubrn_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 19 | string: string, 20 | uniffi_out_err: UniffiRustCallStatus 21 | ): Uint8Array; 22 | ubrn_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 23 | buffer: Uint8Array, 24 | uniffi_out_err: UniffiRustCallStatus 25 | ): string; 26 | ubrn_ffi_matrix_sdk_crypto_uniffi_contract_version(): number; 27 | } 28 | 29 | // Casting globalThis to any allows us to look for `NativeMatrixSdkCrypto` 30 | // if it was added via JSI. 31 | // 32 | // We use a getter here rather than simply `globalThis.NativeMatrixSdkCrypto` so that 33 | // if/when the startup sequence isn't just so, an empty value isn't inadvertantly cached. 34 | const getter: () => NativeModuleInterface = () => 35 | (globalThis as any).NativeMatrixSdkCrypto; 36 | export default getter; 37 | 38 | // Structs and function types for calling back into Typescript from Rust. 39 | export type UniffiRustFutureContinuationCallback = ( 40 | data: bigint, 41 | pollResult: number 42 | ) => void; 43 | type UniffiForeignFutureFree = (handle: bigint) => void; 44 | type UniffiCallbackInterfaceFree = (handle: bigint) => void; 45 | export type UniffiForeignFuture = { 46 | handle: bigint; 47 | free: UniffiForeignFutureFree; 48 | }; 49 | export type UniffiForeignFutureStructU8 = { 50 | returnValue: number; 51 | callStatus: UniffiRustCallStatus; 52 | }; 53 | export type UniffiForeignFutureCompleteU8 = ( 54 | callbackData: bigint, 55 | result: UniffiForeignFutureStructU8 56 | ) => void; 57 | export type UniffiForeignFutureStructI8 = { 58 | returnValue: number; 59 | callStatus: UniffiRustCallStatus; 60 | }; 61 | export type UniffiForeignFutureCompleteI8 = ( 62 | callbackData: bigint, 63 | result: UniffiForeignFutureStructI8 64 | ) => void; 65 | export type UniffiForeignFutureStructU16 = { 66 | returnValue: number; 67 | callStatus: UniffiRustCallStatus; 68 | }; 69 | export type UniffiForeignFutureCompleteU16 = ( 70 | callbackData: bigint, 71 | result: UniffiForeignFutureStructU16 72 | ) => void; 73 | export type UniffiForeignFutureStructI16 = { 74 | returnValue: number; 75 | callStatus: UniffiRustCallStatus; 76 | }; 77 | export type UniffiForeignFutureCompleteI16 = ( 78 | callbackData: bigint, 79 | result: UniffiForeignFutureStructI16 80 | ) => void; 81 | export type UniffiForeignFutureStructU32 = { 82 | returnValue: number; 83 | callStatus: UniffiRustCallStatus; 84 | }; 85 | export type UniffiForeignFutureCompleteU32 = ( 86 | callbackData: bigint, 87 | result: UniffiForeignFutureStructU32 88 | ) => void; 89 | export type UniffiForeignFutureStructI32 = { 90 | returnValue: number; 91 | callStatus: UniffiRustCallStatus; 92 | }; 93 | export type UniffiForeignFutureCompleteI32 = ( 94 | callbackData: bigint, 95 | result: UniffiForeignFutureStructI32 96 | ) => void; 97 | export type UniffiForeignFutureStructU64 = { 98 | returnValue: bigint; 99 | callStatus: UniffiRustCallStatus; 100 | }; 101 | export type UniffiForeignFutureCompleteU64 = ( 102 | callbackData: bigint, 103 | result: UniffiForeignFutureStructU64 104 | ) => void; 105 | export type UniffiForeignFutureStructI64 = { 106 | returnValue: bigint; 107 | callStatus: UniffiRustCallStatus; 108 | }; 109 | export type UniffiForeignFutureCompleteI64 = ( 110 | callbackData: bigint, 111 | result: UniffiForeignFutureStructI64 112 | ) => void; 113 | export type UniffiForeignFutureStructF32 = { 114 | returnValue: number; 115 | callStatus: UniffiRustCallStatus; 116 | }; 117 | export type UniffiForeignFutureCompleteF32 = ( 118 | callbackData: bigint, 119 | result: UniffiForeignFutureStructF32 120 | ) => void; 121 | export type UniffiForeignFutureStructF64 = { 122 | returnValue: number; 123 | callStatus: UniffiRustCallStatus; 124 | }; 125 | export type UniffiForeignFutureCompleteF64 = ( 126 | callbackData: bigint, 127 | result: UniffiForeignFutureStructF64 128 | ) => void; 129 | export type UniffiForeignFutureStructPointer = { 130 | returnValue: bigint; 131 | callStatus: UniffiRustCallStatus; 132 | }; 133 | export type UniffiForeignFutureCompletePointer = ( 134 | callbackData: bigint, 135 | result: UniffiForeignFutureStructPointer 136 | ) => void; 137 | export type UniffiForeignFutureStructRustBuffer = { 138 | returnValue: Uint8Array; 139 | callStatus: UniffiRustCallStatus; 140 | }; 141 | export type UniffiForeignFutureCompleteRustBuffer = ( 142 | callbackData: bigint, 143 | result: UniffiForeignFutureStructRustBuffer 144 | ) => void; 145 | export type UniffiForeignFutureStructVoid = { 146 | callStatus: UniffiRustCallStatus; 147 | }; 148 | export type UniffiForeignFutureCompleteVoid = ( 149 | callbackData: bigint, 150 | result: UniffiForeignFutureStructVoid 151 | ) => void; 152 | 153 | // UniffiRustFutureContinuationCallback is generated as part of the component interface's 154 | // ffi_definitions. However, we need it in the runtime. 155 | // We could: 156 | // (a) do some complicated template logic to ensure the declaration is not generated here (possible) 157 | // (b) import the generated declaration into the runtime (m a y b e) or… 158 | // (c) generate the declaration anyway, and use a different declaration in the runtime. 159 | // 160 | // We chose (c) here as the simplest. In addition, we perform a compile time check that 161 | // the two versions of `UniffiRustFutureContinuationCallback` are structurally equivalent. 162 | // 163 | // If you see the error: 164 | // ``` 165 | // Type 'true' is not assignable to type 'false'.(2322) 166 | // ``` 167 | // Then a new version of uniffi has changed the signature of the callback. Most likely, code in 168 | // `typescript/src/async-rust-call.ts` will need to be changed. 169 | // 170 | // If you see the error: 171 | // ``` 172 | // Cannot find name 'UniffiRustFutureContinuationCallback'. Did you mean 'RuntimeUniffiRustFutureContinuationCallback'?(2552) 173 | // ``` 174 | // then you may not be using callbacks or promises, and uniffi is now not generating Futures and callbacks. 175 | // You should not generate this if that is the case. 176 | // 177 | // ('You' being the bindings generator maintainer). 178 | const isRustFutureContinuationCallbackTypeCompatible: UniffiStructuralEquality< 179 | RuntimeUniffiRustFutureContinuationCallback, 180 | UniffiRustFutureContinuationCallback 181 | > = true; 182 | const isUniffiForeignFutureTypeCompatible: UniffiStructuralEquality< 183 | RuntimeUniffiForeignFuture, 184 | UniffiForeignFuture 185 | > = true; 186 | -------------------------------------------------------------------------------- /src/generated/matrix_sdk-ffi.ts: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. 2 | // Trust me, you don't want to mess with it! 3 | 4 | import { 5 | type StructuralEquality as UniffiStructuralEquality, 6 | type UniffiForeignFuture as RuntimeUniffiForeignFuture, 7 | type UniffiRustCallStatus, 8 | type UniffiRustArcPtr, 9 | type UniffiRustFutureContinuationCallback as RuntimeUniffiRustFutureContinuationCallback, 10 | type UniffiResult, 11 | } from 'uniffi-bindgen-react-native'; 12 | 13 | interface NativeModuleInterface { 14 | ubrn_uniffi_internal_fn_func_ffi__string_to_byte_length( 15 | string: string, 16 | uniffi_out_err: UniffiRustCallStatus 17 | ): number; 18 | ubrn_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 19 | string: string, 20 | uniffi_out_err: UniffiRustCallStatus 21 | ): Uint8Array; 22 | ubrn_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 23 | buffer: Uint8Array, 24 | uniffi_out_err: UniffiRustCallStatus 25 | ): string; 26 | ubrn_uniffi_matrix_sdk_fn_clone_oauthauthorizationdata( 27 | ptr: bigint, 28 | uniffi_out_err: UniffiRustCallStatus 29 | ): bigint; 30 | ubrn_uniffi_matrix_sdk_fn_free_oauthauthorizationdata( 31 | ptr: bigint, 32 | uniffi_out_err: UniffiRustCallStatus 33 | ): void; 34 | ubrn_uniffi_matrix_sdk_fn_method_oauthauthorizationdata_login_url( 35 | ptr: bigint, 36 | uniffi_out_err: UniffiRustCallStatus 37 | ): Uint8Array; 38 | ubrn_uniffi_matrix_sdk_checksum_method_oauthauthorizationdata_login_url(): number; 39 | ubrn_ffi_matrix_sdk_uniffi_contract_version(): number; 40 | ubrn_uniffi_internal_fn_method_oauthauthorizationdata_ffi__bless_pointer( 41 | pointer: bigint, 42 | uniffi_out_err: UniffiRustCallStatus 43 | ): UniffiRustArcPtr; 44 | } 45 | 46 | // Casting globalThis to any allows us to look for `NativeMatrixSdk` 47 | // if it was added via JSI. 48 | // 49 | // We use a getter here rather than simply `globalThis.NativeMatrixSdk` so that 50 | // if/when the startup sequence isn't just so, an empty value isn't inadvertantly cached. 51 | const getter: () => NativeModuleInterface = () => 52 | (globalThis as any).NativeMatrixSdk; 53 | export default getter; 54 | 55 | // Structs and function types for calling back into Typescript from Rust. 56 | export type UniffiRustFutureContinuationCallback = ( 57 | data: bigint, 58 | pollResult: number 59 | ) => void; 60 | type UniffiForeignFutureFree = (handle: bigint) => void; 61 | type UniffiCallbackInterfaceFree = (handle: bigint) => void; 62 | export type UniffiForeignFuture = { 63 | handle: bigint; 64 | free: UniffiForeignFutureFree; 65 | }; 66 | export type UniffiForeignFutureStructU8 = { 67 | returnValue: number; 68 | callStatus: UniffiRustCallStatus; 69 | }; 70 | export type UniffiForeignFutureCompleteU8 = ( 71 | callbackData: bigint, 72 | result: UniffiForeignFutureStructU8 73 | ) => void; 74 | export type UniffiForeignFutureStructI8 = { 75 | returnValue: number; 76 | callStatus: UniffiRustCallStatus; 77 | }; 78 | export type UniffiForeignFutureCompleteI8 = ( 79 | callbackData: bigint, 80 | result: UniffiForeignFutureStructI8 81 | ) => void; 82 | export type UniffiForeignFutureStructU16 = { 83 | returnValue: number; 84 | callStatus: UniffiRustCallStatus; 85 | }; 86 | export type UniffiForeignFutureCompleteU16 = ( 87 | callbackData: bigint, 88 | result: UniffiForeignFutureStructU16 89 | ) => void; 90 | export type UniffiForeignFutureStructI16 = { 91 | returnValue: number; 92 | callStatus: UniffiRustCallStatus; 93 | }; 94 | export type UniffiForeignFutureCompleteI16 = ( 95 | callbackData: bigint, 96 | result: UniffiForeignFutureStructI16 97 | ) => void; 98 | export type UniffiForeignFutureStructU32 = { 99 | returnValue: number; 100 | callStatus: UniffiRustCallStatus; 101 | }; 102 | export type UniffiForeignFutureCompleteU32 = ( 103 | callbackData: bigint, 104 | result: UniffiForeignFutureStructU32 105 | ) => void; 106 | export type UniffiForeignFutureStructI32 = { 107 | returnValue: number; 108 | callStatus: UniffiRustCallStatus; 109 | }; 110 | export type UniffiForeignFutureCompleteI32 = ( 111 | callbackData: bigint, 112 | result: UniffiForeignFutureStructI32 113 | ) => void; 114 | export type UniffiForeignFutureStructU64 = { 115 | returnValue: bigint; 116 | callStatus: UniffiRustCallStatus; 117 | }; 118 | export type UniffiForeignFutureCompleteU64 = ( 119 | callbackData: bigint, 120 | result: UniffiForeignFutureStructU64 121 | ) => void; 122 | export type UniffiForeignFutureStructI64 = { 123 | returnValue: bigint; 124 | callStatus: UniffiRustCallStatus; 125 | }; 126 | export type UniffiForeignFutureCompleteI64 = ( 127 | callbackData: bigint, 128 | result: UniffiForeignFutureStructI64 129 | ) => void; 130 | export type UniffiForeignFutureStructF32 = { 131 | returnValue: number; 132 | callStatus: UniffiRustCallStatus; 133 | }; 134 | export type UniffiForeignFutureCompleteF32 = ( 135 | callbackData: bigint, 136 | result: UniffiForeignFutureStructF32 137 | ) => void; 138 | export type UniffiForeignFutureStructF64 = { 139 | returnValue: number; 140 | callStatus: UniffiRustCallStatus; 141 | }; 142 | export type UniffiForeignFutureCompleteF64 = ( 143 | callbackData: bigint, 144 | result: UniffiForeignFutureStructF64 145 | ) => void; 146 | export type UniffiForeignFutureStructPointer = { 147 | returnValue: bigint; 148 | callStatus: UniffiRustCallStatus; 149 | }; 150 | export type UniffiForeignFutureCompletePointer = ( 151 | callbackData: bigint, 152 | result: UniffiForeignFutureStructPointer 153 | ) => void; 154 | export type UniffiForeignFutureStructRustBuffer = { 155 | returnValue: Uint8Array; 156 | callStatus: UniffiRustCallStatus; 157 | }; 158 | export type UniffiForeignFutureCompleteRustBuffer = ( 159 | callbackData: bigint, 160 | result: UniffiForeignFutureStructRustBuffer 161 | ) => void; 162 | export type UniffiForeignFutureStructVoid = { 163 | callStatus: UniffiRustCallStatus; 164 | }; 165 | export type UniffiForeignFutureCompleteVoid = ( 166 | callbackData: bigint, 167 | result: UniffiForeignFutureStructVoid 168 | ) => void; 169 | 170 | // UniffiRustFutureContinuationCallback is generated as part of the component interface's 171 | // ffi_definitions. However, we need it in the runtime. 172 | // We could: 173 | // (a) do some complicated template logic to ensure the declaration is not generated here (possible) 174 | // (b) import the generated declaration into the runtime (m a y b e) or… 175 | // (c) generate the declaration anyway, and use a different declaration in the runtime. 176 | // 177 | // We chose (c) here as the simplest. In addition, we perform a compile time check that 178 | // the two versions of `UniffiRustFutureContinuationCallback` are structurally equivalent. 179 | // 180 | // If you see the error: 181 | // ``` 182 | // Type 'true' is not assignable to type 'false'.(2322) 183 | // ``` 184 | // Then a new version of uniffi has changed the signature of the callback. Most likely, code in 185 | // `typescript/src/async-rust-call.ts` will need to be changed. 186 | // 187 | // If you see the error: 188 | // ``` 189 | // Cannot find name 'UniffiRustFutureContinuationCallback'. Did you mean 'RuntimeUniffiRustFutureContinuationCallback'?(2552) 190 | // ``` 191 | // then you may not be using callbacks or promises, and uniffi is now not generating Futures and callbacks. 192 | // You should not generate this if that is the case. 193 | // 194 | // ('You' being the bindings generator maintainer). 195 | const isRustFutureContinuationCallbackTypeCompatible: UniffiStructuralEquality< 196 | RuntimeUniffiRustFutureContinuationCallback, 197 | UniffiRustFutureContinuationCallback 198 | > = true; 199 | const isUniffiForeignFutureTypeCompatible: UniffiStructuralEquality< 200 | RuntimeUniffiForeignFuture, 201 | UniffiForeignFuture 202 | > = true; 203 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@unomed/react-native-matrix-sdk", 3 | "version": "0.8.1", 4 | "description": "⚡️ FFI bindings for matrix-rust-sdk in a React Native Turbo Module ⚡️", 5 | "source": "./src/index.tsx", 6 | "main": "./lib/commonjs/index.js", 7 | "module": "./lib/module/index.js", 8 | "exports": { 9 | ".": { 10 | "import": { 11 | "types": "./lib/typescript/module/src/index.d.ts", 12 | "default": "./lib/module/index.js" 13 | }, 14 | "require": { 15 | "types": "./lib/typescript/commonjs/src/index.d.ts", 16 | "default": "./lib/commonjs/index.js" 17 | } 18 | } 19 | }, 20 | "files": [ 21 | "src", 22 | "lib", 23 | "android", 24 | "ios", 25 | "cpp", 26 | "*.podspec", 27 | "react-native.config.js", 28 | "swift", 29 | "scripts", 30 | "!ios/build", 31 | "!android/build", 32 | "!android/gradle", 33 | "!android/gradlew", 34 | "!android/gradlew.bat", 35 | "!android/local.properties", 36 | "!**/__tests__", 37 | "!**/__fixtures__", 38 | "!**/__mocks__", 39 | "!**/.*" 40 | ], 41 | "scripts": { 42 | "ubrn:android:build": "CARGO_TARGET_X86_64_LINUX_ANDROID_RUSTFLAGS=\"-L$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/lib/clang/17/lib/linux\" ubrn build android --config ubrn.yaml --native-bindings", 43 | "ubrn:android:build:release": "yarn ubrn:android:build --release", 44 | "ubrn:ios:build": "CARGO_FEATURE_NO_NEON=1 ubrn build ios --config ubrn.yaml --native-bindings --and-generate", 45 | "ubrn:ios:build:release": "yarn ubrn:ios:build --release", 46 | "ubrn:ios:post-process": "del-cli swift && mv ios/swift swift && (cd example/ios && pod install) && rm -rf src/index.web.ts", 47 | "ubrn:checkout": "( test -d rust_modules/matrix-rust-sdk && git -C rust_modules/matrix-rust-sdk reset --hard HEAD ); ubrn checkout --config ubrn.yaml && ( cd rust_modules/matrix-rust-sdk && git apply ../../matrix-rust-sdk.patch )", 48 | "ubrn:clean": "del-cli -v cpp android/src/main/java ios \"src/Native*\" src/generated \"src/index.ts*\"", 49 | "ubrn:clean:android": "del-cli -v android/src/main/java \"src/Native*\" src/generated \"src/index.ts*\"", 50 | "ubrn:clean:ios": "del-cli -v ios swift \"src/Native*\" src/generated \"src/index.ts*\"", 51 | "generate": "yarn ubrn:clean && yarn ubrn:checkout && yarn ubrn:android:build && yarn ubrn:ios:build && yarn ubrn:ios:generate", 52 | "generate:android": "yarn ubrn:clean:android && yarn ubrn:checkout && yarn ubrn:android:build --and-generate && node scripts/sort-uniffi-calls.js", 53 | "generate:ios": "yarn ubrn:clean:ios && yarn ubrn:checkout && yarn ubrn:ios:build && yarn ubrn:ios:post-process", 54 | "generate:release": "yarn generate:release:android && yarn generate:release:ios", 55 | "generate:release:android": "yarn ubrn:clean:android && yarn ubrn:checkout && yarn ubrn:android:build:release --and-generate && node scripts/sort-uniffi-calls.js", 56 | "generate:release:ios": "yarn ubrn:clean:ios && yarn ubrn:checkout && yarn ubrn:ios:build:release && yarn ubrn:ios:post-process", 57 | "format": "prettier -w '**/*.{ts,tsx}'", 58 | "example": "yarn workspace @unomed/react-native-matrix-sdk-example", 59 | "typecheck": "tsc", 60 | "lint": "eslint \"**/*.{js,ts,tsx}\"", 61 | "clean": "del-cli -v android/build example/android/build example/android/app/build example/ios/build lib **/.cxx", 62 | "prepare": "bob build", 63 | "release": "release-it", 64 | "postinstall": "patch-package && node scripts/download-binaries.js" 65 | }, 66 | "keywords": [ 67 | "react-native", 68 | "ios", 69 | "android", 70 | "matrix" 71 | ], 72 | "repository": { 73 | "type": "git", 74 | "url": "git+https://github.com/unomed-dev/react-native-matrix-sdk.git" 75 | }, 76 | "author": "Johannes Marbach (https://github.com/Johennes)", 77 | "license": "Apache-2.0", 78 | "bugs": { 79 | "url": "https://github.com/unomed-dev/react-native-matrix-sdk/issues" 80 | }, 81 | "homepage": "https://github.com/unomed-dev/react-native-matrix-sdk#readme", 82 | "publishConfig": { 83 | "registry": "https://registry.npmjs.org/" 84 | }, 85 | "devDependencies": { 86 | "@commitlint/config-conventional": "^17.0.2", 87 | "@evilmartians/lefthook": "^1.5.0", 88 | "@react-native-community/cli": "15.0.1", 89 | "@react-native/eslint-config": "0.76.9", 90 | "@release-it/conventional-changelog": "^5.0.0", 91 | "@types/jest": "^29.5.5", 92 | "@types/react": "^18.2.44", 93 | "commitlint": "^17.0.2", 94 | "del-cli": "^5.1.0", 95 | "eslint": "^8.51.0", 96 | "eslint-config-prettier": "^9.0.0", 97 | "eslint-plugin-prettier": "^5.0.1", 98 | "jest": "^29.7.0", 99 | "prettier": "^3.0.3", 100 | "react": "18.3.1", 101 | "react-native": "0.76.9", 102 | "react-native-builder-bob": "^0.31.0", 103 | "release-it": "^15.0.0", 104 | "turbo": "^1.10.7", 105 | "typescript": "^5.2.2" 106 | }, 107 | "resolutions": { 108 | "@types/react": "^18.2.44" 109 | }, 110 | "peerDependencies": { 111 | "react": "*", 112 | "react-native": "*" 113 | }, 114 | "workspaces": [ 115 | "example" 116 | ], 117 | "packageManager": "yarn@3.6.1", 118 | "jest": { 119 | "preset": "react-native", 120 | "modulePathIgnorePatterns": [ 121 | "/example/node_modules", 122 | "/lib/" 123 | ] 124 | }, 125 | "commitlint": { 126 | "extends": [ 127 | "@commitlint/config-conventional" 128 | ] 129 | }, 130 | "release-it": { 131 | "git": { 132 | "commitMessage": "chore: release ${version}", 133 | "tagName": "${version}", 134 | "addUntrackedFiles": true 135 | }, 136 | "npm": { 137 | "publish": true 138 | }, 139 | "github": { 140 | "release": true, 141 | "assets": [ 142 | "binaries.tar.gz" 143 | ] 144 | }, 145 | "hooks": { 146 | "before:release": "yarn generate:release && node scripts/package-binaries.js", 147 | "after:bump": "git add example/ios/Podfile.lock" 148 | }, 149 | "plugins": { 150 | "@release-it/conventional-changelog": { 151 | "preset": "angular" 152 | } 153 | } 154 | }, 155 | "eslintConfig": { 156 | "root": true, 157 | "extends": [ 158 | "@react-native", 159 | "prettier" 160 | ], 161 | "rules": { 162 | "react/react-in-jsx-scope": "off", 163 | "prettier/prettier": [ 164 | "error", 165 | { 166 | "quoteProps": "consistent", 167 | "singleQuote": true, 168 | "tabWidth": 2, 169 | "trailingComma": "es5", 170 | "useTabs": false 171 | } 172 | ] 173 | } 174 | }, 175 | "eslintIgnore": [ 176 | "node_modules/", 177 | "lib/" 178 | ], 179 | "prettier": { 180 | "quoteProps": "consistent", 181 | "singleQuote": true, 182 | "tabWidth": 2, 183 | "trailingComma": "es5", 184 | "useTabs": false 185 | }, 186 | "react-native-builder-bob": { 187 | "source": "src", 188 | "output": "lib", 189 | "targets": [ 190 | "codegen", 191 | [ 192 | "commonjs", 193 | { 194 | "esm": true 195 | } 196 | ], 197 | [ 198 | "module", 199 | { 200 | "esm": true 201 | } 202 | ], 203 | [ 204 | "typescript", 205 | { 206 | "project": "tsconfig.build.json", 207 | "esm": true 208 | } 209 | ] 210 | ] 211 | }, 212 | "codegenConfig": { 213 | "name": "RNReactNativeMatrixSdkSpec", 214 | "type": "all", 215 | "jsSrcsDir": "src", 216 | "outputDir": { 217 | "ios": "ios/generated", 218 | "android": "android/generated" 219 | }, 220 | "android": { 221 | "javaPackageName": "com.unomed.reactnativematrixsdk" 222 | }, 223 | "includesGeneratedCode": true 224 | }, 225 | "create-react-native-library": { 226 | "type": "module-new", 227 | "languages": "cpp", 228 | "version": "0.41.2" 229 | }, 230 | "dependencies": { 231 | "patch-package": "^8.0.0", 232 | "postinstall-postinstall": "^2.1.0", 233 | "tar": "^7.4.3", 234 | "uniffi-bindgen-react-native": "0.29.3-1" 235 | } 236 | } 237 | -------------------------------------------------------------------------------- /example/android/gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s 90 | ' "$PWD" ) || exit 91 | 92 | # Use the maximum available, or set MAX_FD != -1 to use that value. 93 | MAX_FD=maximum 94 | 95 | warn () { 96 | echo "$*" 97 | } >&2 98 | 99 | die () { 100 | echo 101 | echo "$*" 102 | echo 103 | exit 1 104 | } >&2 105 | 106 | # OS specific support (must be 'true' or 'false'). 107 | cygwin=false 108 | msys=false 109 | darwin=false 110 | nonstop=false 111 | case "$( uname )" in #( 112 | CYGWIN* ) cygwin=true ;; #( 113 | Darwin* ) darwin=true ;; #( 114 | MSYS* | MINGW* ) msys=true ;; #( 115 | NONSTOP* ) nonstop=true ;; 116 | esac 117 | 118 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 119 | 120 | 121 | # Determine the Java command to use to start the JVM. 122 | if [ -n "$JAVA_HOME" ] ; then 123 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 124 | # IBM's JDK on AIX uses strange locations for the executables 125 | JAVACMD=$JAVA_HOME/jre/sh/java 126 | else 127 | JAVACMD=$JAVA_HOME/bin/java 128 | fi 129 | if [ ! -x "$JAVACMD" ] ; then 130 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 131 | 132 | Please set the JAVA_HOME variable in your environment to match the 133 | location of your Java installation." 134 | fi 135 | else 136 | JAVACMD=java 137 | if ! command -v java >/dev/null 2>&1 138 | then 139 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 140 | 141 | Please set the JAVA_HOME variable in your environment to match the 142 | location of your Java installation." 143 | fi 144 | fi 145 | 146 | # Increase the maximum file descriptors if we can. 147 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 148 | case $MAX_FD in #( 149 | max*) 150 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 151 | # shellcheck disable=SC2039,SC3045 152 | MAX_FD=$( ulimit -H -n ) || 153 | warn "Could not query maximum file descriptor limit" 154 | esac 155 | case $MAX_FD in #( 156 | '' | soft) :;; #( 157 | *) 158 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 159 | # shellcheck disable=SC2039,SC3045 160 | ulimit -n "$MAX_FD" || 161 | warn "Could not set maximum file descriptor limit to $MAX_FD" 162 | esac 163 | fi 164 | 165 | # Collect all arguments for the java command, stacking in reverse order: 166 | # * args from the command line 167 | # * the main class name 168 | # * -classpath 169 | # * -D...appname settings 170 | # * --module-path (only if needed) 171 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 172 | 173 | # For Cygwin or MSYS, switch paths to Windows format before running java 174 | if "$cygwin" || "$msys" ; then 175 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 176 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 177 | 178 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 179 | 180 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 181 | for arg do 182 | if 183 | case $arg in #( 184 | -*) false ;; # don't mess with options #( 185 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 186 | [ -e "$t" ] ;; #( 187 | *) false ;; 188 | esac 189 | then 190 | arg=$( cygpath --path --ignore --mixed "$arg" ) 191 | fi 192 | # Roll the args list around exactly as many times as the number of 193 | # args, so each arg winds up back in the position where it started, but 194 | # possibly modified. 195 | # 196 | # NB: a `for` loop captures its iteration list before it begins, so 197 | # changing the positional parameters here affects neither the number of 198 | # iterations, nor the values presented in `arg`. 199 | shift # remove old arg 200 | set -- "$@" "$arg" # push replacement arg 201 | done 202 | fi 203 | 204 | 205 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 206 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 207 | 208 | # Collect all arguments for the java command: 209 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 210 | # and any embedded shellness will be escaped. 211 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 212 | # treated as '${Hostname}' itself on the command line. 213 | 214 | set -- \ 215 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 216 | -classpath "$CLASSPATH" \ 217 | org.gradle.wrapper.GradleWrapperMain \ 218 | "$@" 219 | 220 | # Stop when "xargs" is not available. 221 | if ! command -v xargs >/dev/null 2>&1 222 | then 223 | die "xargs is not available" 224 | fi 225 | 226 | # Use "xargs" to parse quoted args. 227 | # 228 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 229 | # 230 | # In Bash we could simply go: 231 | # 232 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 233 | # set -- "${ARGS[@]}" "$@" 234 | # 235 | # but POSIX shell has neither arrays nor command substitution, so instead we 236 | # post-process each arg (as a line of input to sed) to backslash-escape any 237 | # character that might be a shell metacharacter, then use eval to reverse 238 | # that process (while maintaining the separation between arguments), and wrap 239 | # the whole thing up as a single "set" statement. 240 | # 241 | # This will of course break if any of these variables contains a newline or 242 | # an unmatched quote. 243 | # 244 | 245 | eval "set -- $( 246 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 247 | xargs -n1 | 248 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 249 | tr '\n' ' ' 250 | )" '"$@"' 251 | 252 | exec "$JAVACMD" "$@" 253 | -------------------------------------------------------------------------------- /matrix-rust-sdk.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Cargo.lock b/Cargo.lock 2 | index 17625d434..451eb3d2d 100644 3 | --- a/Cargo.lock 4 | +++ b/Cargo.lock 5 | @@ -217,43 +217,44 @@ checksum = "9dbc3a507a82b17ba0d98f6ce8fd6954ea0c8152e98009d36a40d8dcc8ce078a" 6 | 7 | [[package]] 8 | name = "askama" 9 | -version = "0.12.1" 10 | +version = "0.13.1" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | -checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" 13 | +checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" 14 | dependencies = [ 15 | "askama_derive", 16 | - "askama_escape", 17 | + "itoa", 18 | + "percent-encoding", 19 | + "serde", 20 | + "serde_json", 21 | ] 22 | 23 | [[package]] 24 | name = "askama_derive" 25 | -version = "0.12.5" 26 | +version = "0.13.1" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | -checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83" 29 | +checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" 30 | dependencies = [ 31 | "askama_parser", 32 | "basic-toml", 33 | - "mime", 34 | - "mime_guess", 35 | + "memchr", 36 | "proc-macro2", 37 | "quote", 38 | + "rustc-hash 2.0.0", 39 | "serde", 40 | + "serde_derive", 41 | "syn", 42 | ] 43 | 44 | -[[package]] 45 | -name = "askama_escape" 46 | -version = "0.10.3" 47 | -source = "registry+https://github.com/rust-lang/crates.io-index" 48 | -checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" 49 | - 50 | [[package]] 51 | name = "askama_parser" 52 | -version = "0.2.1" 53 | +version = "0.13.0" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | -checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" 56 | +checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f" 57 | dependencies = [ 58 | - "nom", 59 | + "memchr", 60 | + "serde", 61 | + "serde_derive", 62 | + "winnow 0.7.13", 63 | ] 64 | 65 | [[package]] 66 | @@ -670,16 +671,16 @@ dependencies = [ 67 | 68 | [[package]] 69 | name = "cargo_metadata" 70 | -version = "0.15.4" 71 | +version = "0.19.2" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" 74 | +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" 75 | dependencies = [ 76 | "camino", 77 | "cargo-platform", 78 | "semver", 79 | "serde", 80 | "serde_json", 81 | - "thiserror 1.0.63", 82 | + "thiserror 2.0.16", 83 | ] 84 | 85 | [[package]] 86 | @@ -3650,16 +3651,6 @@ version = "0.1.54" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "cbf6f36070878c42c5233846cd3de24cf9016828fd47bc22957a687298bb21fc" 89 | 90 | -[[package]] 91 | -name = "mime_guess" 92 | -version = "2.0.5" 93 | -source = "registry+https://github.com/rust-lang/crates.io-index" 94 | -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 95 | -dependencies = [ 96 | - "mime", 97 | - "unicase", 98 | -] 99 | - 100 | [[package]] 101 | name = "minicov" 102 | version = "0.3.7" 103 | @@ -6073,7 +6064,7 @@ dependencies = [ 104 | "serde", 105 | "serde_spanned", 106 | "toml_datetime", 107 | - "winnow", 108 | + "winnow 0.6.20", 109 | ] 110 | 111 | [[package]] 112 | @@ -6339,17 +6330,19 @@ checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" 113 | 114 | [[package]] 115 | name = "uniffi" 116 | -version = "0.28.0" 117 | +version = "0.29.4" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | -checksum = "f31bff6daf87277a9014bcdefbc2842b0553392919d1096843c5aad899ca4588" 120 | +checksum = "c6d968cb62160c11f2573e6be724ef8b1b18a277aededd17033f8a912d73e2b4" 121 | dependencies = [ 122 | "anyhow", 123 | "camino", 124 | + "cargo_metadata", 125 | "clap", 126 | "uniffi_bindgen", 127 | "uniffi_build", 128 | "uniffi_core", 129 | "uniffi_macros", 130 | + "uniffi_pipeline", 131 | ] 132 | 133 | [[package]] 134 | @@ -6361,9 +6354,9 @@ dependencies = [ 135 | 136 | [[package]] 137 | name = "uniffi_bindgen" 138 | -version = "0.28.0" 139 | +version = "0.29.4" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | -checksum = "96061d7e01b185aa405f7c9b134741ab3e50cc6796a47d6fd8ab9a5364b5feed" 142 | +checksum = "f6b39ef1acbe1467d5d210f274fae344cb6f8766339330cb4c9688752899bf6b" 143 | dependencies = [ 144 | "anyhow", 145 | "askama", 146 | @@ -6373,60 +6366,61 @@ dependencies = [ 147 | "glob", 148 | "goblin", 149 | "heck", 150 | + "indexmap", 151 | "once_cell", 152 | - "paste", 153 | "serde", 154 | + "tempfile", 155 | "textwrap", 156 | "toml 0.5.11", 157 | + "uniffi_internal_macros", 158 | "uniffi_meta", 159 | - "uniffi_testing", 160 | + "uniffi_pipeline", 161 | "uniffi_udl", 162 | ] 163 | 164 | [[package]] 165 | name = "uniffi_build" 166 | -version = "0.28.0" 167 | +version = "0.29.4" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | -checksum = "9d6b86f9b221046af0c533eafe09ece04e2f1ded04ccdc9bba0ec09aec1c52bd" 170 | +checksum = "6683e6b665423cddeacd89a3f97312cf400b2fb245a26f197adaf65c45d505b2" 171 | dependencies = [ 172 | "anyhow", 173 | "camino", 174 | "uniffi_bindgen", 175 | ] 176 | 177 | -[[package]] 178 | -name = "uniffi_checksum_derive" 179 | -version = "0.28.3" 180 | -source = "registry+https://github.com/rust-lang/crates.io-index" 181 | -checksum = "802d2051a700e3ec894c79f80d2705b69d85844dafbbe5d1a92776f8f48b563a" 182 | -dependencies = [ 183 | - "quote", 184 | - "syn", 185 | -] 186 | - 187 | [[package]] 188 | name = "uniffi_core" 189 | -version = "0.28.0" 190 | +version = "0.29.4" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | -checksum = "3210d57d6ab6065ab47a2898dacdb7c606fd6a4156196831fa3bf82e34ac58a6" 193 | +checksum = "c2d990b553d6b9a7ee9c3ae71134674739913d52350b56152b0e613595bb5a6f" 194 | dependencies = [ 195 | "anyhow", 196 | "async-compat", 197 | "bytes", 198 | - "camino", 199 | - "log", 200 | "once_cell", 201 | - "paste", 202 | "static_assertions", 203 | ] 204 | 205 | +[[package]] 206 | +name = "uniffi_internal_macros" 207 | +version = "0.29.4" 208 | +source = "registry+https://github.com/rust-lang/crates.io-index" 209 | +checksum = "04f4f224becf14885c10e6e400b95cc4d1985738140cb194ccc2044563f8a56b" 210 | +dependencies = [ 211 | + "anyhow", 212 | + "indexmap", 213 | + "proc-macro2", 214 | + "quote", 215 | + "syn", 216 | +] 217 | + 218 | [[package]] 219 | name = "uniffi_macros" 220 | -version = "0.28.0" 221 | +version = "0.29.4" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | -checksum = "b58691741080935437dc862122e68d7414432a11824ac1137868de46181a0bd2" 224 | +checksum = "b481d385af334871d70904e6a5f129be7cd38c18fcf8dd8fd1f646b426a56d58" 225 | dependencies = [ 226 | - "bincode", 227 | "camino", 228 | "fs-err", 229 | "once_cell", 230 | @@ -6440,39 +6434,38 @@ dependencies = [ 231 | 232 | [[package]] 233 | name = "uniffi_meta" 234 | -version = "0.28.0" 235 | +version = "0.29.4" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | -checksum = "7663eacdbd9fbf4a88907ddcfe2e6fa85838eb6dc2418a7d91eebb3786f8e20b" 238 | +checksum = "10f817868a3b171bb7bf259e882138d104deafde65684689b4694c846d322491" 239 | dependencies = [ 240 | "anyhow", 241 | - "bytes", 242 | "siphasher 0.3.11", 243 | - "uniffi_checksum_derive", 244 | + "uniffi_internal_macros", 245 | + "uniffi_pipeline", 246 | ] 247 | 248 | [[package]] 249 | -name = "uniffi_testing" 250 | -version = "0.28.0" 251 | +name = "uniffi_pipeline" 252 | +version = "0.29.4" 253 | source = "registry+https://github.com/rust-lang/crates.io-index" 254 | -checksum = "f922465f7566f25f8fe766920205fdfa9a3fcdc209c6bfb7557f0b5bf45b04dd" 255 | +checksum = "4b147e133ad7824e32426b90bc41fda584363563f2ba747f590eca1fd6fd14e6" 256 | dependencies = [ 257 | "anyhow", 258 | - "camino", 259 | - "cargo_metadata", 260 | - "fs-err", 261 | - "once_cell", 262 | + "heck", 263 | + "indexmap", 264 | + "tempfile", 265 | + "uniffi_internal_macros", 266 | ] 267 | 268 | [[package]] 269 | name = "uniffi_udl" 270 | -version = "0.28.0" 271 | +version = "0.29.4" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | -checksum = "cef408229a3a407fafa4c36dc4f6ece78a6fb258ab28d2b64bddd49c8cb680f6" 274 | +checksum = "caed654fb73da5abbc7a7e9c741532284532ba4762d6fe5071372df22a41730a" 275 | dependencies = [ 276 | "anyhow", 277 | "textwrap", 278 | "uniffi_meta", 279 | - "uniffi_testing", 280 | "weedle2", 281 | ] 282 | 283 | @@ -7182,6 +7175,15 @@ dependencies = [ 284 | "memchr", 285 | ] 286 | 287 | +[[package]] 288 | +name = "winnow" 289 | +version = "0.7.13" 290 | +source = "registry+https://github.com/rust-lang/crates.io-index" 291 | +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" 292 | +dependencies = [ 293 | + "memchr", 294 | +] 295 | + 296 | [[package]] 297 | name = "wiremock" 298 | version = "0.6.5" 299 | diff --git a/Cargo.toml b/Cargo.toml 300 | index 399e7b6f6..45cec4598 100644 301 | --- a/Cargo.toml 302 | +++ b/Cargo.toml 303 | @@ -102,8 +102,8 @@ tracing-appender = "0.2.3" 304 | tracing-core = "0.1.34" 305 | tracing-subscriber = "0.3.20" 306 | unicode-normalization = "0.1.24" 307 | -uniffi = { version = "0.28.0" } 308 | -uniffi_bindgen = { version = "0.28.0" } 309 | +uniffi = { version = "0.29.4" } 310 | +uniffi_bindgen = { version = "0.29.4" } 311 | url = "2.5.7" 312 | uuid = "1.18.0" 313 | vergen-gitcl = "1.0.8" 314 | diff --git a/bindings/matrix-sdk-ffi/src/api.udl b/bindings/matrix-sdk-ffi/src/api.udl 315 | index c7caa1afb..c5fa1c1ff 100644 316 | --- a/bindings/matrix-sdk-ffi/src/api.udl 317 | +++ b/bindings/matrix-sdk-ffi/src/api.udl 318 | @@ -1,10 +1,12 @@ 319 | namespace matrix_sdk_ffi {}; 320 | 321 | +[Remote] 322 | dictionary Mentions { 323 | sequence user_ids; 324 | boolean room; 325 | }; 326 | 327 | +[Remote] 328 | interface RoomMessageEventContentWithoutRelation { 329 | RoomMessageEventContentWithoutRelation with_mentions(Mentions mentions); 330 | }; 331 | diff --git a/xtask/src/swift.rs b/xtask/src/swift.rs 332 | index bf8e7f345..a2a315553 100644 333 | --- a/xtask/src/swift.rs 334 | +++ b/xtask/src/swift.rs 335 | @@ -8,6 +8,7 @@ use clap::{Args, Subcommand}; 336 | use uniffi_bindgen::{bindings::SwiftBindingGenerator, library_mode::generate_bindings}; 337 | use xshell::cmd; 338 | 339 | +use cargo_metadata::MetadataCommand; 340 | use crate::{Result, sh, workspace}; 341 | 342 | /// Builds the SDK for Swift as a Static Library or XCFramework. 343 | @@ -185,7 +186,12 @@ fn build_library() -> Result<()> { 344 | } 345 | 346 | fn generate_uniffi(library_path: &Utf8Path, ffi_directory: &Utf8Path) -> Result<()> { 347 | - generate_bindings(library_path, None, &SwiftBindingGenerator, None, ffi_directory, false)?; 348 | + let manifest_path = std::env::current_dir()?.join("Cargo.toml"); 349 | + println!("manifest path {:?}", manifest_path); 350 | + let metadata = MetadataCommand::new().manifest_path(manifest_path).exec()?; 351 | + let config_supplier = CrateConfigSupplier::from(metadata); 352 | + 353 | + generate_bindings(library_path, None, &SwiftBindingGenerator, &config_supplier, None, ffi_directory, false)?; 354 | Ok(()) 355 | } 356 | 357 | -------------------------------------------------------------------------------- /src/generated/matrix_sdk_base.ts: -------------------------------------------------------------------------------- 1 | // This file was autogenerated by some hot garbage in the `uniffi-bindgen-react-native` crate. 2 | // Trust me, you don't want to mess with it! 3 | import nativeModule, { 4 | type UniffiRustFutureContinuationCallback, 5 | type UniffiForeignFuture, 6 | type UniffiForeignFutureStructU8, 7 | type UniffiForeignFutureCompleteU8, 8 | type UniffiForeignFutureStructI8, 9 | type UniffiForeignFutureCompleteI8, 10 | type UniffiForeignFutureStructU16, 11 | type UniffiForeignFutureCompleteU16, 12 | type UniffiForeignFutureStructI16, 13 | type UniffiForeignFutureCompleteI16, 14 | type UniffiForeignFutureStructU32, 15 | type UniffiForeignFutureCompleteU32, 16 | type UniffiForeignFutureStructI32, 17 | type UniffiForeignFutureCompleteI32, 18 | type UniffiForeignFutureStructU64, 19 | type UniffiForeignFutureCompleteU64, 20 | type UniffiForeignFutureStructI64, 21 | type UniffiForeignFutureCompleteI64, 22 | type UniffiForeignFutureStructF32, 23 | type UniffiForeignFutureCompleteF32, 24 | type UniffiForeignFutureStructF64, 25 | type UniffiForeignFutureCompleteF64, 26 | type UniffiForeignFutureStructPointer, 27 | type UniffiForeignFutureCompletePointer, 28 | type UniffiForeignFutureStructRustBuffer, 29 | type UniffiForeignFutureCompleteRustBuffer, 30 | type UniffiForeignFutureStructVoid, 31 | type UniffiForeignFutureCompleteVoid, 32 | } from './matrix_sdk_base-ffi'; 33 | import { 34 | type UniffiByteArray, 35 | type UniffiDuration, 36 | AbstractFfiConverterByteArray, 37 | FfiConverterBool, 38 | FfiConverterDuration, 39 | FfiConverterInt32, 40 | FfiConverterOptional, 41 | FfiConverterUInt64, 42 | RustBuffer, 43 | UniffiInternalError, 44 | UniffiRustCaller, 45 | uniffiCreateFfiConverterString, 46 | uniffiCreateRecord, 47 | } from 'uniffi-bindgen-react-native'; 48 | 49 | // Get converters from the other files, if any. 50 | const uniffiCaller = new UniffiRustCaller(() => ({ code: 0 })); 51 | 52 | const uniffiIsDebug = 53 | // @ts-ignore -- The process global might not be defined 54 | typeof process !== 'object' || 55 | // @ts-ignore -- The process global might not be defined 56 | process?.env?.NODE_ENV !== 'production' || 57 | false; 58 | // Public interface members begin here. 59 | 60 | /** 61 | * The retention policy for media content used by the [`EventCacheStore`]. 62 | * 63 | * [`EventCacheStore`]: crate::event_cache::store::EventCacheStore 64 | */ 65 | export type MediaRetentionPolicy = { 66 | /** 67 | * The maximum authorized size of the overall media cache, in bytes. 68 | * 69 | * The cache size is defined as the sum of the sizes of all the (possibly 70 | * encrypted) media contents in the cache, excluding any metadata 71 | * associated with them. 72 | * 73 | * If this is set and the cache size is bigger than this value, the oldest 74 | * media contents in the cache will be removed during a cleanup until the 75 | * cache size is below this threshold. 76 | * 77 | * Note that it is possible for the cache size to temporarily exceed this 78 | * value between two cleanups. 79 | * 80 | * Defaults to 400 MiB. 81 | */ 82 | maxCacheSize: /*u64*/ bigint | undefined; 83 | /** 84 | * The maximum authorized size of a single media content, in bytes. 85 | * 86 | * The size of a media content is the size taken by the content in the 87 | * database, after it was possibly encrypted, so it might differ from the 88 | * initial size of the content. 89 | * 90 | * The maximum authorized size of a single media content is actually the 91 | * lowest value between `max_cache_size` and `max_file_size`. 92 | * 93 | * If it is set, media content bigger than the maximum size will not be 94 | * cached. If the maximum size changed after media content that exceeds the 95 | * new value was cached, the corresponding content will be removed 96 | * during a cleanup. 97 | * 98 | * Defaults to 20 MiB. 99 | */ 100 | maxFileSize: /*u64*/ bigint | undefined; 101 | /** 102 | * The duration after which unaccessed media content is considered 103 | * expired. 104 | * 105 | * If this is set, media content whose last access is older than this 106 | * duration will be removed from the media cache during a cleanup. 107 | * 108 | * Defaults to 60 days. 109 | */ 110 | lastAccessExpiry: UniffiDuration | undefined; 111 | /** 112 | * The duration between two automatic media cache cleanups. 113 | * 114 | * If this is set, a cleanup will be triggered after the given duration 115 | * is elapsed, at the next call to the media cache API. If this is set to 116 | * zero, each call to the media cache API will trigger a cleanup. If this 117 | * is `None`, cleanups will only occur if they are triggered manually. 118 | * 119 | * Defaults to running cleanups daily. 120 | */ 121 | cleanupFrequency: UniffiDuration | undefined; 122 | }; 123 | 124 | /** 125 | * Generated factory for {@link MediaRetentionPolicy} record objects. 126 | */ 127 | export const MediaRetentionPolicy = (() => { 128 | const defaults = () => ({}); 129 | const create = (() => { 130 | return uniffiCreateRecord< 131 | MediaRetentionPolicy, 132 | ReturnType 133 | >(defaults); 134 | })(); 135 | return Object.freeze({ 136 | /** 137 | * Create a frozen instance of {@link MediaRetentionPolicy}, with defaults specified 138 | * in Rust, in the {@link matrix_sdk_base} crate. 139 | */ 140 | create, 141 | 142 | /** 143 | * Create a frozen instance of {@link MediaRetentionPolicy}, with defaults specified 144 | * in Rust, in the {@link matrix_sdk_base} crate. 145 | */ 146 | new: create, 147 | 148 | /** 149 | * Defaults specified in the {@link matrix_sdk_base} crate. 150 | */ 151 | defaults: () => Object.freeze(defaults()) as Partial, 152 | }); 153 | })(); 154 | 155 | const FfiConverterTypeMediaRetentionPolicy = (() => { 156 | type TypeName = MediaRetentionPolicy; 157 | class FFIConverter extends AbstractFfiConverterByteArray { 158 | read(from: RustBuffer): TypeName { 159 | return { 160 | maxCacheSize: FfiConverterOptionalUInt64.read(from), 161 | maxFileSize: FfiConverterOptionalUInt64.read(from), 162 | lastAccessExpiry: FfiConverterOptionalDuration.read(from), 163 | cleanupFrequency: FfiConverterOptionalDuration.read(from), 164 | }; 165 | } 166 | write(value: TypeName, into: RustBuffer): void { 167 | FfiConverterOptionalUInt64.write(value.maxCacheSize, into); 168 | FfiConverterOptionalUInt64.write(value.maxFileSize, into); 169 | FfiConverterOptionalDuration.write(value.lastAccessExpiry, into); 170 | FfiConverterOptionalDuration.write(value.cleanupFrequency, into); 171 | } 172 | allocationSize(value: TypeName): number { 173 | return ( 174 | FfiConverterOptionalUInt64.allocationSize(value.maxCacheSize) + 175 | FfiConverterOptionalUInt64.allocationSize(value.maxFileSize) + 176 | FfiConverterOptionalDuration.allocationSize(value.lastAccessExpiry) + 177 | FfiConverterOptionalDuration.allocationSize(value.cleanupFrequency) 178 | ); 179 | } 180 | } 181 | return new FFIConverter(); 182 | })(); 183 | 184 | const stringConverter = { 185 | stringToBytes: (s: string) => 186 | uniffiCaller.rustCall((status) => 187 | nativeModule().ubrn_uniffi_internal_fn_func_ffi__string_to_arraybuffer( 188 | s, 189 | status 190 | ) 191 | ), 192 | bytesToString: (ab: UniffiByteArray) => 193 | uniffiCaller.rustCall((status) => 194 | nativeModule().ubrn_uniffi_internal_fn_func_ffi__arraybuffer_to_string( 195 | ab, 196 | status 197 | ) 198 | ), 199 | stringByteLength: (s: string) => 200 | uniffiCaller.rustCall((status) => 201 | nativeModule().ubrn_uniffi_internal_fn_func_ffi__string_to_byte_length( 202 | s, 203 | status 204 | ) 205 | ), 206 | }; 207 | const FfiConverterString = uniffiCreateFfiConverterString(stringConverter); 208 | 209 | /** 210 | * Represents the state of a room encryption. 211 | */ 212 | export enum EncryptionState { 213 | /** 214 | * The room is encrypted. 215 | */ 216 | Encrypted, 217 | /** 218 | * The room is not encrypted. 219 | */ 220 | NotEncrypted, 221 | /** 222 | * The state of the room encryption is unknown, probably because the 223 | * `/sync` did not provide all data needed to decide. 224 | */ 225 | Unknown, 226 | } 227 | 228 | const FfiConverterTypeEncryptionState = (() => { 229 | const ordinalConverter = FfiConverterInt32; 230 | type TypeName = EncryptionState; 231 | class FFIConverter extends AbstractFfiConverterByteArray { 232 | read(from: RustBuffer): TypeName { 233 | switch (ordinalConverter.read(from)) { 234 | case 1: 235 | return EncryptionState.Encrypted; 236 | case 2: 237 | return EncryptionState.NotEncrypted; 238 | case 3: 239 | return EncryptionState.Unknown; 240 | default: 241 | throw new UniffiInternalError.UnexpectedEnumCase(); 242 | } 243 | } 244 | write(value: TypeName, into: RustBuffer): void { 245 | switch (value) { 246 | case EncryptionState.Encrypted: 247 | return ordinalConverter.write(1, into); 248 | case EncryptionState.NotEncrypted: 249 | return ordinalConverter.write(2, into); 250 | case EncryptionState.Unknown: 251 | return ordinalConverter.write(3, into); 252 | } 253 | } 254 | allocationSize(value: TypeName): number { 255 | return ordinalConverter.allocationSize(0); 256 | } 257 | } 258 | return new FFIConverter(); 259 | })(); 260 | 261 | // FfiConverter for UniffiDuration | undefined 262 | const FfiConverterOptionalDuration = new FfiConverterOptional( 263 | FfiConverterDuration 264 | ); 265 | 266 | // FfiConverter for /*u64*/bigint | undefined 267 | const FfiConverterOptionalUInt64 = new FfiConverterOptional(FfiConverterUInt64); 268 | 269 | /** 270 | * This should be called before anything else. 271 | * 272 | * It is likely that this is being done for you by the library's `index.ts`. 273 | * 274 | * It checks versions of uniffi between when the Rust scaffolding was generated 275 | * and when the bindings were generated. 276 | * 277 | * It also initializes the machinery to enable Rust to talk back to Javascript. 278 | */ 279 | function uniffiEnsureInitialized() { 280 | // Get the bindings contract version from our ComponentInterface 281 | const bindingsContractVersion = 29; 282 | // Get the scaffolding contract version by calling the into the dylib 283 | const scaffoldingContractVersion = 284 | nativeModule().ubrn_ffi_matrix_sdk_base_uniffi_contract_version(); 285 | if (bindingsContractVersion !== scaffoldingContractVersion) { 286 | throw new UniffiInternalError.ContractVersionMismatch( 287 | scaffoldingContractVersion, 288 | bindingsContractVersion 289 | ); 290 | } 291 | } 292 | 293 | export default Object.freeze({ 294 | initialize: uniffiEnsureInitialized, 295 | converters: { 296 | FfiConverterTypeEncryptionState, 297 | FfiConverterTypeMediaRetentionPolicy, 298 | }, 299 | }); 300 | --------------------------------------------------------------------------------