diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 5ce42bc..d505a09 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -52,8 +52,35 @@ jobs: working-directory: packages/react-native-sandbox run: npm pack + test: + runs-on: macos-15 + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install asdf + uses: asdf-vm/actions/setup@v4 + + - name: Tools cache + id: asdf-cache + uses: actions/cache@v4 + with: + path: ~/.asdf/ + key: ${{ runner.os }}-${{ hashFiles('**/.tool-versions') }} + + - name: Install tools from .tool-versions + if: steps.asdf-cache.outputs.cache-hit != 'true' + uses: asdf-vm/actions/install@v4 + + - name: Install dependencies + run: bun install --frozen-lockfile + + - name: Run Test + run: bun run test + example-compilation: runs-on: macos-15 + needs: [lint, test] strategy: matrix: example: [demo] # side-by-side, recursive, fs-experiment diff --git a/README.md b/README.md index 29c7001..550850c 100644 --- a/README.md +++ b/README.md @@ -142,9 +142,13 @@ AppRegistry.registerComponent("SandboxApp", () => App); Full examples: +- [`apps/demo`](./apps/demo/README.md): Security demo. - [`apps/side-by-side`](./apps/side-by-side/README.md): An example application with two sandbox instances. - [`apps/recursive`](./apps/recursive/README.md): An example application with few nested sandbox instances. -- [`apps/demo`](./apps/demo/README.md): Security demo. +- [`apps/p2p-counter`](./apps/p2p-counter/README.md): Direct sandbox-to-sandbox communication demo. + + + ## 📚 API Reference @@ -155,7 +159,7 @@ For comprehensive API documentation, installation instructions, and advanced usa We're actively working on expanding the capabilities of `react-native-sandbox`. Here's what's planned: - [ ] **Android Support** - Full cross-platform compatibility -- [ ] **Inter-Sandbox Communication** - Secure direct communication between sandbox instances +- [x] **Inter-Sandbox Communication** - Secure direct communication between sandbox instances - [ ] **[RE.Pack](https://github.com/callstack/repack) Integration** - Advanced bundling and module federation - Hot-reloading for sandbox instances in development - Dynamic bundle fetching from remote sources diff --git a/apps/demo/App.tsx b/apps/demo/App.tsx index 4ec0823..605f70e 100644 --- a/apps/demo/App.tsx +++ b/apps/demo/App.tsx @@ -5,7 +5,7 @@ import Toast from 'react-native-toast-message' import CrashIfYouCanDemo from './CrashIfYouCanDemo' -const SideBySideDemo: React.FC = () => { +const DemoApp: React.FC = () => { return ( @@ -69,4 +69,4 @@ const styles = StyleSheet.create({ }, }) -export default SideBySideDemo +export default DemoApp diff --git a/apps/demo/ios/Demo/Images.xcassets/cs-gradient.imageset/Contents.json b/apps/demo/ios/Demo/Images.xcassets/cs-gradient.imageset/Contents.json new file mode 100644 index 0000000..4136700 --- /dev/null +++ b/apps/demo/ios/Demo/Images.xcassets/cs-gradient.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} \ No newline at end of file diff --git a/apps/demo/ios/Demo/Images.xcassets/cs-gradient.imageset/cs-gradient.png b/apps/demo/ios/Demo/Images.xcassets/cs-gradient.imageset/cs-gradient.png new file mode 120000 index 0000000..18a2f5e --- /dev/null +++ b/apps/demo/ios/Demo/Images.xcassets/cs-gradient.imageset/cs-gradient.png @@ -0,0 +1 @@ +../../../../../../docs/images/cs-gradient.png \ No newline at end of file diff --git a/apps/demo/ios/Demo/LaunchScreen.storyboard b/apps/demo/ios/Demo/LaunchScreen.storyboard index 1caf840..b50c607 100644 --- a/apps/demo/ios/Demo/LaunchScreen.storyboard +++ b/apps/demo/ios/Demo/LaunchScreen.storyboard @@ -1,10 +1,11 @@ - + - + + @@ -16,27 +17,46 @@ - - + + + + + + + + - + - @@ -44,4 +64,10 @@ + + + + + + diff --git a/apps/demo/ios/Podfile.lock b/apps/demo/ios/Podfile.lock index 1a6e339..764b717 100644 --- a/apps/demo/ios/Podfile.lock +++ b/apps/demo/ios/Podfile.lock @@ -2019,7 +2019,7 @@ PODS: - React-timing - React-utils - SocketRocket - - React-Sandbox (0.2.0): + - React-Sandbox (0.4.0): - boost - DoubleConversion - fast_float @@ -2451,7 +2451,7 @@ SPEC CHECKSUMS: React-runtimeexecutor: 17c70842d5e611130cb66f91e247bc4a609c3508 React-RuntimeHermes: 3c88e6e1ea7ea0899dcffc77c10d61ea46688cfd React-runtimescheduler: 024500621c7c93d65371498abb4ee26d34f5d47d - React-Sandbox: 789583cf1f6db8c2bf95e54125aef4314fe9d8ca + React-Sandbox: e3cf3c955559ed9f0bf014b29dce1e94600cd790 React-timing: c3c923df2b86194e1682e01167717481232f1dc7 React-utils: 9154a037543147e1c24098f1a48fc8472602c092 ReactAppDependencyProvider: afd905e84ee36e1678016ae04d7370c75ed539be diff --git a/apps/demo/jest.config.js b/apps/demo/jest.config.js index 1fbafc9..f9902db 100644 --- a/apps/demo/jest.config.js +++ b/apps/demo/jest.config.js @@ -1,3 +1,7 @@ module.exports = { preset: 'react-native', + transformIgnorePatterns: [ + 'node_modules/(?!(react-native|@react-native|@react-native-community|@callstack/react-native-sandbox|react-native-toast-message|react-native-reanimated)/)', + ], + setupFilesAfterEnv: ['/../../jest.setup.js'], } diff --git a/apps/demo/package.json b/apps/demo/package.json index 5956b31..26b6849 100644 --- a/apps/demo/package.json +++ b/apps/demo/package.json @@ -6,7 +6,8 @@ "android": "react-native run-android", "ios": "react-native run-ios", "start": "react-native start", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "test": "jest" }, "dependencies": { "react": "19.1.0", diff --git a/apps/fs-experiment/ios/MultInstance-FSExperiment/Images.xcassets/cs-gradient.imageset/Contents.json b/apps/fs-experiment/ios/MultInstance-FSExperiment/Images.xcassets/cs-gradient.imageset/Contents.json new file mode 100644 index 0000000..4136700 --- /dev/null +++ b/apps/fs-experiment/ios/MultInstance-FSExperiment/Images.xcassets/cs-gradient.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} \ No newline at end of file diff --git a/apps/fs-experiment/ios/MultInstance-FSExperiment/Images.xcassets/cs-gradient.imageset/cs-gradient.png b/apps/fs-experiment/ios/MultInstance-FSExperiment/Images.xcassets/cs-gradient.imageset/cs-gradient.png new file mode 120000 index 0000000..18a2f5e --- /dev/null +++ b/apps/fs-experiment/ios/MultInstance-FSExperiment/Images.xcassets/cs-gradient.imageset/cs-gradient.png @@ -0,0 +1 @@ +../../../../../../docs/images/cs-gradient.png \ No newline at end of file diff --git a/apps/fs-experiment/ios/MultInstance-FSExperiment/LaunchScreen.storyboard b/apps/fs-experiment/ios/MultInstance-FSExperiment/LaunchScreen.storyboard index 0024765..c1b36e9 100644 --- a/apps/fs-experiment/ios/MultInstance-FSExperiment/LaunchScreen.storyboard +++ b/apps/fs-experiment/ios/MultInstance-FSExperiment/LaunchScreen.storyboard @@ -1,6 +1,8 @@ + + @@ -12,17 +14,31 @@ - + - @@ -32,8 +48,14 @@ + + + + + + - + @@ -44,6 +66,7 @@ + diff --git a/apps/fs-experiment/ios/Podfile.lock b/apps/fs-experiment/ios/Podfile.lock index e3c0f61..607299b 100644 --- a/apps/fs-experiment/ios/Podfile.lock +++ b/apps/fs-experiment/ios/Podfile.lock @@ -2019,7 +2019,7 @@ PODS: - React-timing - React-utils - SocketRocket - - React-Sandbox (0.2.0): + - React-Sandbox (0.4.0): - boost - DoubleConversion - fast_float @@ -2491,7 +2491,7 @@ SPEC CHECKSUMS: React-runtimeexecutor: 17c70842d5e611130cb66f91e247bc4a609c3508 React-RuntimeHermes: 3c88e6e1ea7ea0899dcffc77c10d61ea46688cfd React-runtimescheduler: 024500621c7c93d65371498abb4ee26d34f5d47d - React-Sandbox: 789583cf1f6db8c2bf95e54125aef4314fe9d8ca + React-Sandbox: e3cf3c955559ed9f0bf014b29dce1e94600cd790 React-timing: c3c923df2b86194e1682e01167717481232f1dc7 React-utils: 9154a037543147e1c24098f1a48fc8472602c092 ReactAppDependencyProvider: afd905e84ee36e1678016ae04d7370c75ed539be diff --git a/apps/fs-experiment/package.json b/apps/fs-experiment/package.json index cf4c45e..384693a 100644 --- a/apps/fs-experiment/package.json +++ b/apps/fs-experiment/package.json @@ -9,7 +9,8 @@ "bundle:sandbox": "bun run bundle:sandbox-fs && bun run bundle:sandbox-file-access", "bundle:sandbox-fs": "npx react-native bundle --platform ios --dev false --entry-file sandbox-fs.js --bundle-output ios/sandbox-fs.jsbundle --assets-dest ios/", "bundle:sandbox-file-access": "npx react-native bundle --platform ios --dev false --entry-file sandbox-file-access.js --bundle-output ios/sandbox-file-access.jsbundle --assets-dest ios/", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "jest": "echo 'No tests'" }, "dependencies": { "react": "19.1.0", diff --git a/apps/p2p-chat/.bundle/config b/apps/p2p-chat/.bundle/config new file mode 100644 index 0000000..848943b --- /dev/null +++ b/apps/p2p-chat/.bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/apps/p2p-chat/README.md b/apps/p2p-chat/README.md new file mode 100644 index 0000000..feae3b4 --- /dev/null +++ b/apps/p2p-chat/README.md @@ -0,0 +1,13 @@ +# P2P Chat Carousel + +![Platform: iOS](https://img.shields.io/badge/platform-iOS-blue.svg) + +This example demonstrates advanced peer-to-peer communication between multiple isolated React Native sandboxes using `react-native-sandbox`. It features a carousel interface where users can dynamically add/remove chat instances, with each sandbox operating independently while communicating directly with others through a friendship system and real-time messaging. + +The demo showcases dynamic instance management, multi-target communication, friend request handling, and a sophisticated message routing system - all while maintaining complete isolation between sandbox environments. Users can swipe between different chat instances (Alice, Bob, Charlie, Diana, Eve, Frank), send friend requests, accept/reject friendships, and engage in real-time conversations. + +## Screenshot + +
+ +
\ No newline at end of file diff --git a/apps/p2p-chat/__tests__/App.test.tsx b/apps/p2p-chat/__tests__/App.test.tsx new file mode 100644 index 0000000..8e508b3 --- /dev/null +++ b/apps/p2p-chat/__tests__/App.test.tsx @@ -0,0 +1,14 @@ +/** + * @format + */ + +import React from 'react' +import ReactTestRenderer from 'react-test-renderer' + +import App from '../src/App' + +test('renders correctly', async () => { + await ReactTestRenderer.act(() => { + ReactTestRenderer.create() + }) +}) diff --git a/apps/p2p-chat/android/app/build.gradle b/apps/p2p-chat/android/app/build.gradle new file mode 100644 index 0000000..d20fd2e --- /dev/null +++ b/apps/p2p-chat/android/app/build.gradle @@ -0,0 +1,119 @@ +apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: "com.facebook.react" + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '../..' + // root = file("../../") + // The folder where the react-native NPM package is. Default is ../../node_modules/react-native + // reactNativeDir = file("../../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen + // codegenDir = file("../../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js + // cliFile = file("../../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] + + /* Autolinking */ + autolinkLibrariesWithApp() +} + +/** + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' + +android { + ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion + + namespace "com.p2pchat" + defaultConfig { + applicationId "com.p2pchat" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } +} diff --git a/apps/p2p-chat/android/app/debug.keystore b/apps/p2p-chat/android/app/debug.keystore new file mode 100644 index 0000000..364e105 Binary files /dev/null and b/apps/p2p-chat/android/app/debug.keystore differ diff --git a/apps/p2p-chat/android/app/proguard-rules.pro b/apps/p2p-chat/android/app/proguard-rules.pro new file mode 100644 index 0000000..11b0257 --- /dev/null +++ b/apps/p2p-chat/android/app/proguard-rules.pro @@ -0,0 +1,10 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: diff --git a/apps/p2p-chat/android/app/src/debug/AndroidManifest.xml b/apps/p2p-chat/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..eb98c01 --- /dev/null +++ b/apps/p2p-chat/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/apps/p2p-chat/android/app/src/main/AndroidManifest.xml b/apps/p2p-chat/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..e189252 --- /dev/null +++ b/apps/p2p-chat/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/apps/p2p-chat/android/app/src/main/java/com/p2pchat/MainActivity.kt b/apps/p2p-chat/android/app/src/main/java/com/p2pchat/MainActivity.kt new file mode 100644 index 0000000..c7eff90 --- /dev/null +++ b/apps/p2p-chat/android/app/src/main/java/com/p2pchat/MainActivity.kt @@ -0,0 +1,22 @@ +package com.p2pchat + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "P2PChat" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} diff --git a/apps/p2p-chat/android/app/src/main/java/com/p2pchat/MainApplication.kt b/apps/p2p-chat/android/app/src/main/java/com/p2pchat/MainApplication.kt new file mode 100644 index 0000000..c3dc7af --- /dev/null +++ b/apps/p2p-chat/android/app/src/main/java/com/p2pchat/MainApplication.kt @@ -0,0 +1,38 @@ +package com.p2pchat + +import android.app.Application +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost + +class MainApplication : Application(), ReactApplication { + + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + loadReactNative(this) + } +} diff --git a/apps/p2p-chat/android/app/src/main/res/drawable/rn_edit_text_material.xml b/apps/p2p-chat/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000..5c25e72 --- /dev/null +++ b/apps/p2p-chat/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/apps/p2p-chat/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..a2f5908 Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/apps/p2p-chat/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/apps/p2p-chat/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..ff10afd Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/apps/p2p-chat/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/apps/p2p-chat/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..dcd3cd8 Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/apps/p2p-chat/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/apps/p2p-chat/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..8ca12fe Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/apps/p2p-chat/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apps/p2p-chat/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/apps/p2p-chat/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/apps/p2p-chat/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/apps/p2p-chat/android/app/src/main/res/values/strings.xml b/apps/p2p-chat/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..66fbdd1 --- /dev/null +++ b/apps/p2p-chat/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + P2PChat + diff --git a/apps/p2p-chat/android/app/src/main/res/values/styles.xml b/apps/p2p-chat/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..7ba83a2 --- /dev/null +++ b/apps/p2p-chat/android/app/src/main/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/apps/p2p-chat/android/build.gradle b/apps/p2p-chat/android/build.gradle new file mode 100644 index 0000000..b4f3ad9 --- /dev/null +++ b/apps/p2p-chat/android/build.gradle @@ -0,0 +1,21 @@ +buildscript { + ext { + buildToolsVersion = "35.0.0" + minSdkVersion = 24 + compileSdkVersion = 35 + targetSdkVersion = 35 + ndkVersion = "27.1.12297006" + kotlinVersion = "2.1.20" + } + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle") + classpath("com.facebook.react:react-native-gradle-plugin") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") + } +} + +apply plugin: "com.facebook.react.rootproject" diff --git a/apps/p2p-chat/android/gradle.properties b/apps/p2p-chat/android/gradle.properties new file mode 100644 index 0000000..5e24e3a --- /dev/null +++ b/apps/p2p-chat/android/gradle.properties @@ -0,0 +1,39 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=true + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/apps/p2p-chat/android/gradle/wrapper/gradle-wrapper.jar b/apps/p2p-chat/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..1b33c55 Binary files /dev/null and b/apps/p2p-chat/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/apps/p2p-chat/android/gradle/wrapper/gradle-wrapper.properties b/apps/p2p-chat/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..002b867 --- /dev/null +++ b/apps/p2p-chat/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/apps/p2p-chat/android/gradlew b/apps/p2p-chat/android/gradlew new file mode 100755 index 0000000..23d15a9 --- /dev/null +++ b/apps/p2p-chat/android/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/apps/p2p-chat/android/gradlew.bat b/apps/p2p-chat/android/gradlew.bat new file mode 100644 index 0000000..11bf182 --- /dev/null +++ b/apps/p2p-chat/android/gradlew.bat @@ -0,0 +1,99 @@ +@REM Copyright (c) Meta Platforms, Inc. and affiliates. +@REM +@REM This source code is licensed under the MIT license found in the +@REM LICENSE file in the root directory of this source tree. + +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/apps/p2p-chat/android/settings.gradle b/apps/p2p-chat/android/settings.gradle new file mode 100644 index 0000000..6877ac9 --- /dev/null +++ b/apps/p2p-chat/android/settings.gradle @@ -0,0 +1,6 @@ +pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } +plugins { id("com.facebook.react.settings") } +extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } +rootProject.name = 'P2PChat' +include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/apps/p2p-chat/app.json b/apps/p2p-chat/app.json new file mode 100644 index 0000000..a11963a --- /dev/null +++ b/apps/p2p-chat/app.json @@ -0,0 +1,4 @@ +{ + "name": "p2p-chat", + "displayName": "P2P Chat Demo" +} diff --git a/apps/p2p-chat/babel.config.js b/apps/p2p-chat/babel.config.js new file mode 100644 index 0000000..3e0218e --- /dev/null +++ b/apps/p2p-chat/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:@react-native/babel-preset'], +} diff --git a/apps/p2p-chat/docs/screenshot.png b/apps/p2p-chat/docs/screenshot.png new file mode 100644 index 0000000..cd83849 Binary files /dev/null and b/apps/p2p-chat/docs/screenshot.png differ diff --git a/apps/p2p-chat/index.js b/apps/p2p-chat/index.js new file mode 100644 index 0000000..16d08ae --- /dev/null +++ b/apps/p2p-chat/index.js @@ -0,0 +1,11 @@ +import {AppRegistry} from 'react-native' + +import {name as appName} from './app.json' +import App from './src/App' +import ChatApp from './src/ChatApp' + +// Register main app +AppRegistry.registerComponent(appName, () => App) + +// Register chat component for sandbox usage +AppRegistry.registerComponent('ChatApp', () => ChatApp) diff --git a/apps/p2p-chat/ios/.xcode.env b/apps/p2p-chat/ios/.xcode.env new file mode 100644 index 0000000..3d5782c --- /dev/null +++ b/apps/p2p-chat/ios/.xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/apps/p2p-chat/ios/P2PChat.xcodeproj/project.pbxproj b/apps/p2p-chat/ios/P2PChat.xcodeproj/project.pbxproj new file mode 100644 index 0000000..786f769 --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat.xcodeproj/project.pbxproj @@ -0,0 +1,486 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 0C80B921A6F3F58F76C31292 /* libPods-P2PChat.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-P2PChat.a */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + D060FE2E174260A6AAFF51D7 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 13B07F961A680F5B00A75B9A /* P2PChat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = P2PChat.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = P2PChat/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = P2PChat/Info.plist; sourceTree = ""; }; + 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = P2PChat/PrivacyInfo.xcprivacy; sourceTree = ""; }; + 3B4392A12AC88292D35C810B /* Pods-P2PChat.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-P2PChat.debug.xcconfig"; path = "Target Support Files/Pods-P2PChat/Pods-P2PChat.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-P2PChat.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-P2PChat.release.xcconfig"; path = "Target Support Files/Pods-P2PChat/Pods-P2PChat.release.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-P2PChat.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-P2PChat.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = P2PChat/AppDelegate.swift; sourceTree = ""; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = P2PChat/LaunchScreen.storyboard; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80B921A6F3F58F76C31292 /* libPods-P2PChat.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 13B07FAE1A68108700A75B9A /* P2PChat */ = { + isa = PBXGroup; + children = ( + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 761780EC2CA45674006654EE /* AppDelegate.swift */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */, + ); + name = P2PChat; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-P2PChat.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* P2PChat */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* P2PChat.app */, + ); + name = Products; + sourceTree = ""; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-P2PChat.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-P2PChat.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 13B07F861A680F5B00A75B9A /* P2PChat */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "P2PChat" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = P2PChat; + productName = P2PChat; + productReference = 13B07F961A680F5B00A75B9A /* P2PChat.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1120; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "P2PChat" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* P2PChat */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + D060FE2E174260A6AAFF51D7 /* PrivacyInfo.xcprivacy in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-P2PChat/Pods-P2PChat-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-P2PChat/Pods-P2PChat-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-P2PChat/Pods-P2PChat-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-P2PChat-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-P2PChat/Pods-P2PChat-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-P2PChat/Pods-P2PChat-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-P2PChat/Pods-P2PChat-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-P2PChat.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = P2PChat/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = P2PChat; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-P2PChat.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = P2PChat/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = P2PChat; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + "-DFOLLY_HAVE_CLOCK_GETTIME=1", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; + USE_HERMES = true; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.1; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + "-DFOLLY_CFG_NO_COROUTINES=1", + "-DFOLLY_HAVE_CLOCK_GETTIME=1", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + " ", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../../../node_modules/react-native"; + SDKROOT = iphoneos; + USE_HERMES = true; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "P2PChat" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "P2PChat" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/apps/p2p-chat/ios/P2PChat.xcodeproj/xcshareddata/xcschemes/P2PChat.xcscheme b/apps/p2p-chat/ios/P2PChat.xcodeproj/xcshareddata/xcschemes/P2PChat.xcscheme new file mode 100644 index 0000000..c521b91 --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat.xcodeproj/xcshareddata/xcschemes/P2PChat.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/p2p-chat/ios/P2PChat.xcworkspace/contents.xcworkspacedata b/apps/p2p-chat/ios/P2PChat.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..41890df --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/apps/p2p-chat/ios/P2PChat/AppDelegate.swift b/apps/p2p-chat/ios/P2PChat/AppDelegate.swift new file mode 100644 index 0000000..3fe013f --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat/AppDelegate.swift @@ -0,0 +1,48 @@ +import UIKit +import React +import React_RCTAppDelegate +import ReactAppDependencyProvider + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + + var reactNativeDelegate: ReactNativeDelegate? + var reactNativeFactory: RCTReactNativeFactory? + + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil + ) -> Bool { + let delegate = ReactNativeDelegate() + let factory = RCTReactNativeFactory(delegate: delegate) + delegate.dependencyProvider = RCTAppDependencyProvider() + + reactNativeDelegate = delegate + reactNativeFactory = factory + + window = UIWindow(frame: UIScreen.main.bounds) + + factory.startReactNative( + withModuleName: "p2p-chat", + in: window, + launchOptions: launchOptions + ) + + return true + } +} + +class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate { + override func sourceURL(for bridge: RCTBridge) -> URL? { + self.bundleURL() + } + + override func bundleURL() -> URL? { +#if DEBUG + RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") +#else + Bundle.main.url(forResource: "main", withExtension: "jsbundle") +#endif + } +} diff --git a/apps/p2p-chat/ios/P2PChat/Images.xcassets/AppIcon.appiconset/Contents.json b/apps/p2p-chat/ios/P2PChat/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..8121323 --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/apps/p2p-chat/ios/P2PChat/Images.xcassets/Contents.json b/apps/p2p-chat/ios/P2PChat/Images.xcassets/Contents.json new file mode 100644 index 0000000..2d92bd5 --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/apps/p2p-chat/ios/P2PChat/Images.xcassets/cs-gradient.imageset/Contents.json b/apps/p2p-chat/ios/P2PChat/Images.xcassets/cs-gradient.imageset/Contents.json new file mode 100644 index 0000000..4136700 --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat/Images.xcassets/cs-gradient.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "cs-gradient.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} \ No newline at end of file diff --git a/apps/p2p-chat/ios/P2PChat/Images.xcassets/cs-gradient.imageset/cs-gradient.png b/apps/p2p-chat/ios/P2PChat/Images.xcassets/cs-gradient.imageset/cs-gradient.png new file mode 120000 index 0000000..18a2f5e --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat/Images.xcassets/cs-gradient.imageset/cs-gradient.png @@ -0,0 +1 @@ +../../../../../../docs/images/cs-gradient.png \ No newline at end of file diff --git a/apps/p2p-chat/ios/P2PChat/Info.plist b/apps/p2p-chat/ios/P2PChat/Info.plist new file mode 100644 index 0000000..98ca0b8 --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat/Info.plist @@ -0,0 +1,53 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + P2PChat + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking + + + NSLocationWhenInUseUsageDescription + + RCTNewArchEnabled + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/apps/p2p-chat/ios/P2PChat/LaunchScreen.storyboard b/apps/p2p-chat/ios/P2PChat/LaunchScreen.storyboard new file mode 100644 index 0000000..f4f2d59 --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat/LaunchScreen.storyboard @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/p2p-chat/ios/P2PChat/PrivacyInfo.xcprivacy b/apps/p2p-chat/ios/P2PChat/PrivacyInfo.xcprivacy new file mode 100644 index 0000000..41b8317 --- /dev/null +++ b/apps/p2p-chat/ios/P2PChat/PrivacyInfo.xcprivacy @@ -0,0 +1,37 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/apps/p2p-chat/ios/Podfile b/apps/p2p-chat/ios/Podfile new file mode 100644 index 0000000..021e930 --- /dev/null +++ b/apps/p2p-chat/ios/Podfile @@ -0,0 +1,35 @@ +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip + +platform :ios, min_ios_version_supported +prepare_react_native_project! + +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + +target 'P2PChat' do + config = use_native_modules! + + use_react_native!( + :path => config[:reactNativePath], + # An absolute path to your application root. + :app_path => "#{Pod::Config.instance.installation_root}/.." + ) + + post_install do |installer| + # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 + react_native_post_install( + installer, + config[:reactNativePath], + :mac_catalyst_enabled => false, + # :ccache_enabled => true + ) + end +end diff --git a/apps/p2p-chat/ios/Podfile.lock b/apps/p2p-chat/ios/Podfile.lock new file mode 100644 index 0000000..841d6de --- /dev/null +++ b/apps/p2p-chat/ios/Podfile.lock @@ -0,0 +1,2465 @@ +PODS: + - boost (1.84.0) + - DoubleConversion (1.1.6) + - fast_float (8.0.0) + - FBLazyVector (0.80.1) + - fmt (11.0.2) + - glog (0.3.5) + - hermes-engine (0.80.1): + - hermes-engine/Pre-built (= 0.80.1) + - hermes-engine/Pre-built (0.80.1) + - RCT-Folly (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Default (= 2024.11.18.00) + - RCT-Folly/Default (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Fabric (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCTDeprecation (0.80.1) + - RCTRequired (0.80.1) + - RCTTypeSafety (0.80.1): + - FBLazyVector (= 0.80.1) + - RCTRequired (= 0.80.1) + - React-Core (= 0.80.1) + - React (0.80.1): + - React-Core (= 0.80.1) + - React-Core/DevSupport (= 0.80.1) + - React-Core/RCTWebSocket (= 0.80.1) + - React-RCTActionSheet (= 0.80.1) + - React-RCTAnimation (= 0.80.1) + - React-RCTBlob (= 0.80.1) + - React-RCTImage (= 0.80.1) + - React-RCTLinking (= 0.80.1) + - React-RCTNetwork (= 0.80.1) + - React-RCTSettings (= 0.80.1) + - React-RCTText (= 0.80.1) + - React-RCTVibration (= 0.80.1) + - React-callinvoker (0.80.1) + - React-Core (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.80.1) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/CoreModulesHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/Default (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/DevSupport (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.80.1) + - React-Core/RCTWebSocket (= 0.80.1) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTActionSheetHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTAnimationHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTBlobHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTImageHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTLinkingHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTNetworkHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTSettingsHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTTextHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTVibrationHeaders (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTWebSocket (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.80.1) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-CoreModules (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety (= 0.80.1) + - React-Core/CoreModulesHeaders (= 0.80.1) + - React-jsi (= 0.80.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-NativeModulesApple + - React-RCTBlob + - React-RCTFBReactNativeSpec + - React-RCTImage (= 0.80.1) + - ReactCommon + - SocketRocket + - React-cxxreact (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.80.1) + - React-debug (= 0.80.1) + - React-jsi (= 0.80.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-logger (= 0.80.1) + - React-perflogger (= 0.80.1) + - React-runtimeexecutor (= 0.80.1) + - React-timing (= 0.80.1) + - SocketRocket + - React-debug (0.80.1) + - React-defaultsnativemodule (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-domnativemodule + - React-featureflagsnativemodule + - React-hermes + - React-idlecallbacksnativemodule + - React-jsi + - React-jsiexecutor + - React-microtasksnativemodule + - React-RCTFBReactNativeSpec + - SocketRocket + - React-domnativemodule (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Fabric + - React-FabricComponents + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-Fabric (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/animations (= 0.80.1) + - React-Fabric/attributedstring (= 0.80.1) + - React-Fabric/componentregistry (= 0.80.1) + - React-Fabric/componentregistrynative (= 0.80.1) + - React-Fabric/components (= 0.80.1) + - React-Fabric/consistency (= 0.80.1) + - React-Fabric/core (= 0.80.1) + - React-Fabric/dom (= 0.80.1) + - React-Fabric/imagemanager (= 0.80.1) + - React-Fabric/leakchecker (= 0.80.1) + - React-Fabric/mounting (= 0.80.1) + - React-Fabric/observers (= 0.80.1) + - React-Fabric/scheduler (= 0.80.1) + - React-Fabric/telemetry (= 0.80.1) + - React-Fabric/templateprocessor (= 0.80.1) + - React-Fabric/uimanager (= 0.80.1) + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/animations (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/attributedstring (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/componentregistry (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/componentregistrynative (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/components/legacyviewmanagerinterop (= 0.80.1) + - React-Fabric/components/root (= 0.80.1) + - React-Fabric/components/scrollview (= 0.80.1) + - React-Fabric/components/view (= 0.80.1) + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/legacyviewmanagerinterop (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/root (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/scrollview (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/view (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-renderercss + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-Fabric/consistency (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/core (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/dom (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/imagemanager (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/leakchecker (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/mounting (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/observers (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events (= 0.80.1) + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/observers/events (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/scheduler (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-performancetimeline + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/telemetry (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/templateprocessor (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/uimanager (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/uimanager/consistency (= 0.80.1) + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/uimanager/consistency (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-FabricComponents (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components (= 0.80.1) + - React-FabricComponents/textlayoutmanager (= 0.80.1) + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components/inputaccessory (= 0.80.1) + - React-FabricComponents/components/iostextinput (= 0.80.1) + - React-FabricComponents/components/modal (= 0.80.1) + - React-FabricComponents/components/rncore (= 0.80.1) + - React-FabricComponents/components/safeareaview (= 0.80.1) + - React-FabricComponents/components/scrollview (= 0.80.1) + - React-FabricComponents/components/text (= 0.80.1) + - React-FabricComponents/components/textinput (= 0.80.1) + - React-FabricComponents/components/unimplementedview (= 0.80.1) + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/inputaccessory (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/iostextinput (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/modal (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/rncore (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/safeareaview (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/scrollview (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/text (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/textinput (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/unimplementedview (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/textlayoutmanager (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricImage (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired (= 0.80.1) + - RCTTypeSafety (= 0.80.1) + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-jsiexecutor (= 0.80.1) + - React-logger + - React-rendererdebug + - React-utils + - ReactCommon + - SocketRocket + - Yoga + - React-featureflags (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-featureflagsnativemodule (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - React-graphics (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-hermes + - React-jsi + - React-jsiexecutor + - React-utils + - SocketRocket + - React-hermes (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.80.1) + - React-jsi + - React-jsiexecutor (= 0.80.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-perflogger (= 0.80.1) + - React-runtimeexecutor + - SocketRocket + - React-idlecallbacksnativemodule (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-hermes + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimescheduler + - ReactCommon/turbomodule/core + - SocketRocket + - React-ImageManager (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/Default + - React-debug + - React-Fabric + - React-graphics + - React-rendererdebug + - React-utils + - SocketRocket + - React-jserrorhandler (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact + - React-debug + - React-featureflags + - React-jsi + - ReactCommon/turbomodule/bridging + - SocketRocket + - React-jsi (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-jsiexecutor (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.80.1) + - React-jsi (= 0.80.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-perflogger (= 0.80.1) + - SocketRocket + - React-jsinspector (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsi + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-jsinspectortracing + - React-perflogger (= 0.80.1) + - React-runtimeexecutor (= 0.80.1) + - SocketRocket + - React-jsinspectorcdp (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-jsinspectornetwork (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-jsinspectorcdp + - SocketRocket + - React-jsinspectortracing (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-oscompat + - SocketRocket + - React-jsitooling (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.80.1) + - React-jsi (= 0.80.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - SocketRocket + - React-jsitracing (0.80.1): + - React-jsi + - React-logger (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-Mapbuffer (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - SocketRocket + - React-microtasksnativemodule (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-hermes + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - React-NativeModulesApple (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-Core + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-runtimeexecutor + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - React-oscompat (0.80.1) + - React-perflogger (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-performancetimeline (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsinspectortracing + - React-perflogger + - React-timing + - SocketRocket + - React-RCTActionSheet (0.80.1): + - React-Core/RCTActionSheetHeaders (= 0.80.1) + - React-RCTAnimation (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTAnimationHeaders + - React-featureflags + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTAppDelegate (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-CoreModules + - React-debug + - React-defaultsnativemodule + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsitooling + - React-NativeModulesApple + - React-RCTFabric + - React-RCTFBReactNativeSpec + - React-RCTImage + - React-RCTNetwork + - React-RCTRuntime + - React-rendererdebug + - React-RuntimeApple + - React-RuntimeCore + - React-runtimescheduler + - React-utils + - ReactCommon + - SocketRocket + - React-RCTBlob (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/RCTBlobHeaders + - React-Core/RCTWebSocket + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - React-RCTNetwork + - ReactCommon + - SocketRocket + - React-RCTFabric (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core + - React-debug + - React-Fabric + - React-FabricComponents + - React-FabricImage + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-jsinspectortracing + - React-performancetimeline + - React-RCTAnimation + - React-RCTImage + - React-RCTText + - React-rendererconsistency + - React-renderercss + - React-rendererdebug + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-RCTFBReactNativeSpec (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-hermes + - React-jsi + - React-jsiexecutor + - React-NativeModulesApple + - ReactCommon + - SocketRocket + - React-RCTImage (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTImageHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - React-RCTNetwork + - ReactCommon + - SocketRocket + - React-RCTLinking (0.80.1): + - React-Core/RCTLinkingHeaders (= 0.80.1) + - React-jsi (= 0.80.1) + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - ReactCommon/turbomodule/core (= 0.80.1) + - React-RCTNetwork (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTNetworkHeaders + - React-featureflags + - React-jsi + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTRuntime (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core + - React-hermes + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-jsitooling + - React-RuntimeApple + - React-RuntimeCore + - React-RuntimeHermes + - SocketRocket + - React-RCTSettings (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTSettingsHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTText (0.80.1): + - React-Core/RCTTextHeaders (= 0.80.1) + - Yoga + - React-RCTVibration (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/RCTVibrationHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-rendererconsistency (0.80.1) + - React-renderercss (0.80.1): + - React-debug + - React-utils + - React-rendererdebug (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - SocketRocket + - React-rncore (0.80.1) + - React-RuntimeApple (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-Core/Default + - React-CoreModules + - React-cxxreact + - React-featureflags + - React-jserrorhandler + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsitooling + - React-Mapbuffer + - React-NativeModulesApple + - React-RCTFabric + - React-RCTFBReactNativeSpec + - React-RuntimeCore + - React-runtimeexecutor + - React-RuntimeHermes + - React-runtimescheduler + - React-utils + - SocketRocket + - React-RuntimeCore (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact + - React-Fabric + - React-featureflags + - React-hermes + - React-jserrorhandler + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsitooling + - React-performancetimeline + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - React-runtimeexecutor (0.80.1): + - React-jsi (= 0.80.1) + - React-RuntimeHermes (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-hermes + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-jsitooling + - React-jsitracing + - React-RuntimeCore + - React-utils + - SocketRocket + - React-runtimescheduler (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-cxxreact + - React-debug + - React-featureflags + - React-hermes + - React-jsi + - React-jsinspectortracing + - React-performancetimeline + - React-rendererconsistency + - React-rendererdebug + - React-runtimeexecutor + - React-timing + - React-utils + - SocketRocket + - React-Sandbox (0.4.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-timing (0.80.1) + - React-utils (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - React-hermes + - React-jsi (= 0.80.1) + - SocketRocket + - ReactAppDependencyProvider (0.80.1): + - ReactCodegen + - ReactCodegen (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-FabricImage + - React-featureflags + - React-graphics + - React-hermes + - React-jsi + - React-jsiexecutor + - React-NativeModulesApple + - React-RCTAppDelegate + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - ReactCommon (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - ReactCommon/turbomodule (= 0.80.1) + - SocketRocket + - ReactCommon/turbomodule (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.80.1) + - React-cxxreact (= 0.80.1) + - React-jsi (= 0.80.1) + - React-logger (= 0.80.1) + - React-perflogger (= 0.80.1) + - ReactCommon/turbomodule/bridging (= 0.80.1) + - ReactCommon/turbomodule/core (= 0.80.1) + - SocketRocket + - ReactCommon/turbomodule/bridging (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.80.1) + - React-cxxreact (= 0.80.1) + - React-jsi (= 0.80.1) + - React-logger (= 0.80.1) + - React-perflogger (= 0.80.1) + - SocketRocket + - ReactCommon/turbomodule/core (0.80.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.80.1) + - React-cxxreact (= 0.80.1) + - React-debug (= 0.80.1) + - React-featureflags (= 0.80.1) + - React-jsi (= 0.80.1) + - React-logger (= 0.80.1) + - React-perflogger (= 0.80.1) + - React-utils (= 0.80.1) + - SocketRocket + - SocketRocket (0.7.1) + - Yoga (0.0.0) + +DEPENDENCIES: + - boost (from `../../../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - fast_float (from `../../../node_modules/react-native/third-party-podspecs/fast_float.podspec`) + - FBLazyVector (from `../../../node_modules/react-native/Libraries/FBLazyVector`) + - fmt (from `../../../node_modules/react-native/third-party-podspecs/fmt.podspec`) + - glog (from `../../../node_modules/react-native/third-party-podspecs/glog.podspec`) + - hermes-engine (from `../../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - RCT-Folly (from `../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTDeprecation (from `../../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) + - RCTRequired (from `../../../node_modules/react-native/Libraries/Required`) + - RCTTypeSafety (from `../../../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../../../node_modules/react-native/`) + - React-callinvoker (from `../../../node_modules/react-native/ReactCommon/callinvoker`) + - React-Core (from `../../../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../../../node_modules/react-native/`) + - React-CoreModules (from `../../../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../../../node_modules/react-native/ReactCommon/cxxreact`) + - React-debug (from `../../../node_modules/react-native/ReactCommon/react/debug`) + - React-defaultsnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) + - React-domnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/dom`) + - React-Fabric (from `../../../node_modules/react-native/ReactCommon`) + - React-FabricComponents (from `../../../node_modules/react-native/ReactCommon`) + - React-FabricImage (from `../../../node_modules/react-native/ReactCommon`) + - React-featureflags (from `../../../node_modules/react-native/ReactCommon/react/featureflags`) + - React-featureflagsnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) + - React-graphics (from `../../../node_modules/react-native/ReactCommon/react/renderer/graphics`) + - React-hermes (from `../../../node_modules/react-native/ReactCommon/hermes`) + - React-idlecallbacksnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) + - React-ImageManager (from `../../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) + - React-jserrorhandler (from `../../../node_modules/react-native/ReactCommon/jserrorhandler`) + - React-jsi (from `../../../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../../../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsinspectorcdp (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern/cdp`) + - React-jsinspectornetwork (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern/network`) + - React-jsinspectortracing (from `../../../node_modules/react-native/ReactCommon/jsinspector-modern/tracing`) + - React-jsitooling (from `../../../node_modules/react-native/ReactCommon/jsitooling`) + - React-jsitracing (from `../../../node_modules/react-native/ReactCommon/hermes/executor/`) + - React-logger (from `../../../node_modules/react-native/ReactCommon/logger`) + - React-Mapbuffer (from `../../../node_modules/react-native/ReactCommon`) + - React-microtasksnativemodule (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) + - React-NativeModulesApple (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-oscompat (from `../../../node_modules/react-native/ReactCommon/oscompat`) + - React-perflogger (from `../../../node_modules/react-native/ReactCommon/reactperflogger`) + - React-performancetimeline (from `../../../node_modules/react-native/ReactCommon/react/performance/timeline`) + - React-RCTActionSheet (from `../../../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../../../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTAppDelegate (from `../../../node_modules/react-native/Libraries/AppDelegate`) + - React-RCTBlob (from `../../../node_modules/react-native/Libraries/Blob`) + - React-RCTFabric (from `../../../node_modules/react-native/React`) + - React-RCTFBReactNativeSpec (from `../../../node_modules/react-native/React`) + - React-RCTImage (from `../../../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../../../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../../../node_modules/react-native/Libraries/Network`) + - React-RCTRuntime (from `../../../node_modules/react-native/React/Runtime`) + - React-RCTSettings (from `../../../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../../../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../../../node_modules/react-native/Libraries/Vibration`) + - React-rendererconsistency (from `../../../node_modules/react-native/ReactCommon/react/renderer/consistency`) + - React-renderercss (from `../../../node_modules/react-native/ReactCommon/react/renderer/css`) + - React-rendererdebug (from `../../../node_modules/react-native/ReactCommon/react/renderer/debug`) + - React-rncore (from `../../../node_modules/react-native/ReactCommon`) + - React-RuntimeApple (from `../../../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) + - React-RuntimeCore (from `../../../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimeexecutor (from `../../../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-RuntimeHermes (from `../../../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimescheduler (from `../../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) + - "React-Sandbox (from `../../../node_modules/@callstack/react-native-sandbox`)" + - React-timing (from `../../../node_modules/react-native/ReactCommon/react/timing`) + - React-utils (from `../../../node_modules/react-native/ReactCommon/react/utils`) + - ReactAppDependencyProvider (from `build/generated/ios`) + - ReactCodegen (from `build/generated/ios`) + - ReactCommon/turbomodule/core (from `../../../node_modules/react-native/ReactCommon`) + - SocketRocket (~> 0.7.1) + - Yoga (from `../../../node_modules/react-native/ReactCommon/yoga`) + +SPEC REPOS: + trunk: + - SocketRocket + +EXTERNAL SOURCES: + boost: + :podspec: "../../../node_modules/react-native/third-party-podspecs/boost.podspec" + DoubleConversion: + :podspec: "../../../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + fast_float: + :podspec: "../../../node_modules/react-native/third-party-podspecs/fast_float.podspec" + FBLazyVector: + :path: "../../../node_modules/react-native/Libraries/FBLazyVector" + fmt: + :podspec: "../../../node_modules/react-native/third-party-podspecs/fmt.podspec" + glog: + :podspec: "../../../node_modules/react-native/third-party-podspecs/glog.podspec" + hermes-engine: + :podspec: "../../../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + :tag: hermes-2025-05-06-RNv0.80.0-4eb6132a5bf0450bf4c6c91987675381d7ac8bca + RCT-Folly: + :podspec: "../../../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + RCTDeprecation: + :path: "../../../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" + RCTRequired: + :path: "../../../node_modules/react-native/Libraries/Required" + RCTTypeSafety: + :path: "../../../node_modules/react-native/Libraries/TypeSafety" + React: + :path: "../../../node_modules/react-native/" + React-callinvoker: + :path: "../../../node_modules/react-native/ReactCommon/callinvoker" + React-Core: + :path: "../../../node_modules/react-native/" + React-CoreModules: + :path: "../../../node_modules/react-native/React/CoreModules" + React-cxxreact: + :path: "../../../node_modules/react-native/ReactCommon/cxxreact" + React-debug: + :path: "../../../node_modules/react-native/ReactCommon/react/debug" + React-defaultsnativemodule: + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/defaults" + React-domnativemodule: + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/dom" + React-Fabric: + :path: "../../../node_modules/react-native/ReactCommon" + React-FabricComponents: + :path: "../../../node_modules/react-native/ReactCommon" + React-FabricImage: + :path: "../../../node_modules/react-native/ReactCommon" + React-featureflags: + :path: "../../../node_modules/react-native/ReactCommon/react/featureflags" + React-featureflagsnativemodule: + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" + React-graphics: + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/graphics" + React-hermes: + :path: "../../../node_modules/react-native/ReactCommon/hermes" + React-idlecallbacksnativemodule: + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" + React-ImageManager: + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" + React-jserrorhandler: + :path: "../../../node_modules/react-native/ReactCommon/jserrorhandler" + React-jsi: + :path: "../../../node_modules/react-native/ReactCommon/jsi" + React-jsiexecutor: + :path: "../../../node_modules/react-native/ReactCommon/jsiexecutor" + React-jsinspector: + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern" + React-jsinspectorcdp: + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern/cdp" + React-jsinspectornetwork: + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern/network" + React-jsinspectortracing: + :path: "../../../node_modules/react-native/ReactCommon/jsinspector-modern/tracing" + React-jsitooling: + :path: "../../../node_modules/react-native/ReactCommon/jsitooling" + React-jsitracing: + :path: "../../../node_modules/react-native/ReactCommon/hermes/executor/" + React-logger: + :path: "../../../node_modules/react-native/ReactCommon/logger" + React-Mapbuffer: + :path: "../../../node_modules/react-native/ReactCommon" + React-microtasksnativemodule: + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" + React-NativeModulesApple: + :path: "../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + React-oscompat: + :path: "../../../node_modules/react-native/ReactCommon/oscompat" + React-perflogger: + :path: "../../../node_modules/react-native/ReactCommon/reactperflogger" + React-performancetimeline: + :path: "../../../node_modules/react-native/ReactCommon/react/performance/timeline" + React-RCTActionSheet: + :path: "../../../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimation: + :path: "../../../node_modules/react-native/Libraries/NativeAnimation" + React-RCTAppDelegate: + :path: "../../../node_modules/react-native/Libraries/AppDelegate" + React-RCTBlob: + :path: "../../../node_modules/react-native/Libraries/Blob" + React-RCTFabric: + :path: "../../../node_modules/react-native/React" + React-RCTFBReactNativeSpec: + :path: "../../../node_modules/react-native/React" + React-RCTImage: + :path: "../../../node_modules/react-native/Libraries/Image" + React-RCTLinking: + :path: "../../../node_modules/react-native/Libraries/LinkingIOS" + React-RCTNetwork: + :path: "../../../node_modules/react-native/Libraries/Network" + React-RCTRuntime: + :path: "../../../node_modules/react-native/React/Runtime" + React-RCTSettings: + :path: "../../../node_modules/react-native/Libraries/Settings" + React-RCTText: + :path: "../../../node_modules/react-native/Libraries/Text" + React-RCTVibration: + :path: "../../../node_modules/react-native/Libraries/Vibration" + React-rendererconsistency: + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/consistency" + React-renderercss: + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/css" + React-rendererdebug: + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/debug" + React-rncore: + :path: "../../../node_modules/react-native/ReactCommon" + React-RuntimeApple: + :path: "../../../node_modules/react-native/ReactCommon/react/runtime/platform/ios" + React-RuntimeCore: + :path: "../../../node_modules/react-native/ReactCommon/react/runtime" + React-runtimeexecutor: + :path: "../../../node_modules/react-native/ReactCommon/runtimeexecutor" + React-RuntimeHermes: + :path: "../../../node_modules/react-native/ReactCommon/react/runtime" + React-runtimescheduler: + :path: "../../../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" + React-Sandbox: + :path: "../../../node_modules/@callstack/react-native-sandbox" + React-timing: + :path: "../../../node_modules/react-native/ReactCommon/react/timing" + React-utils: + :path: "../../../node_modules/react-native/ReactCommon/react/utils" + ReactAppDependencyProvider: + :path: build/generated/ios + ReactCodegen: + :path: build/generated/ios + ReactCommon: + :path: "../../../node_modules/react-native/ReactCommon" + Yoga: + :path: "../../../node_modules/react-native/ReactCommon/yoga" + +SPEC CHECKSUMS: + boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 + DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb + fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 + FBLazyVector: 09f03e4b6f42f955734b64a118f86509cc719427 + fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd + glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 + hermes-engine: 4f07404533b808de66cf48ac4200463068d0e95a + RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 + RCTDeprecation: efa5010912100e944a7ac9a93a157e1def1988fe + RCTRequired: bbc4cf999ddc4a4b076e076c74dd1d39d0254630 + RCTTypeSafety: d877728097547d0a37786cc9130c43ad71739ac3 + React: 4b0b9cb962e694611e5e8a697c1b0300a2510c21 + React-callinvoker: 70f125c17c7132811a6b473946ac5e7ae93b5e57 + React-Core: bab40f5b1f46fe0c5896895a6f333e861a821a81 + React-CoreModules: 05647d952e521113c128360633896ba7ba652e82 + React-cxxreact: 2b4bac1ec6eecc6288ac8a6caea6afb42585740e + React-debug: deb3a146ef717fa3e8f4c23e0288369fe53199b7 + React-defaultsnativemodule: 11e2948787a15d3cf1b66d7f29f13770a177bff7 + React-domnativemodule: 2f4b279acdb2963736fb5de2f585811dd90070b5 + React-Fabric: 6f8d1a303c96f1d078c14d74c4005bf457e5b782 + React-FabricComponents: b106410970e9a0c4e592da656c7a7e0947306c23 + React-FabricImage: 1abaf230dfce9b58fdf53c4128f3f40c6e64af6a + React-featureflags: f7ef58d91079efde3ad223bcca6d197e845d5bcf + React-featureflagsnativemodule: ae5abc9849d1696f4f8f11ee3744bf5715e032cf + React-graphics: b306856c6ed9aac32f717a229550406a53b28a6d + React-hermes: b6edce8fa19388654b1aea30844497cbeade83bc + React-idlecallbacksnativemodule: cb386712842cb9e479c89311edb234d529b64db4 + React-ImageManager: 8ce94417853eaa22faaad1f4cc1952dd3f8e2275 + React-jserrorhandler: ab827d67dc270a9c8703eef524230baeafaf6876 + React-jsi: 545342ec5c78ab1277af5f0dbe8d489e7e73db14 + React-jsiexecutor: 20210891c7c77255c16dec6762faf68b373f9f74 + React-jsinspector: 4e73460e488132d70d2b4894e5578cc856f2cb74 + React-jsinspectorcdp: 8b2bcb5779289cb2b9ca517f2965ed23eb2fd3e0 + React-jsinspectornetwork: b5e0cb9e488d294eed2d8209dc3dc0f9587210c1 + React-jsinspectortracing: f3c4036e7b984405ac910f878576d325dd9f2834 + React-jsitooling: 75bbfd221b6173a5e848ca5a6680506bac064a56 + React-jsitracing: 11ed7d821864dd988c159d4943e0a1e0937c11b1 + React-logger: 984ebd897afad067555d081deaf03f57c4315723 + React-Mapbuffer: 0c045c844ce6d85cde53e85ab163294c6adad349 + React-microtasksnativemodule: d9499269ad1f484ae71319bac1d9231447f2094e + React-NativeModulesApple: 983f3483ef0a3446b56d490f09d579fba2442e17 + React-oscompat: 114036cd8f064558c9c1a0c04fc9ae5e1453706a + React-perflogger: e7287fee27c16e3c8bd4d470f2361572b63be16b + React-performancetimeline: 8ebbaa31d2d0cea680b0a2a567500d3cab8954fc + React-RCTActionSheet: 68c68b0a7a5d2b0cfc255c64889b6e485974e988 + React-RCTAnimation: d6c5c728b888a967ce9aff1ff71a8ed71a68d069 + React-RCTAppDelegate: 0fc048666bda159cd469a6fb9befb04b3fa62be4 + React-RCTBlob: 12d8c699a1f906840113ee8d8bb575e69a05509f + React-RCTFabric: 01e815845ebc185f44205dcbf50eeb712fec23fe + React-RCTFBReactNativeSpec: f57927fb0af6ce2f25c19f8b894e2986138aa89f + React-RCTImage: a82518168f4ee407913b23ca749ca79ef51959f3 + React-RCTLinking: 7f343b584c36f024f390fea563483568fe763ef6 + React-RCTNetwork: 3165eb757ceb62a7cde4cdad043d63314122e8a3 + React-RCTRuntime: feee590c459c4cb6aaa7a00f3abc8c04709b536f + React-RCTSettings: 6bad0ae45d8d872c873059f332f586f99875621f + React-RCTText: 657d60f35983062de8f0cea67c279aa7a3ea9858 + React-RCTVibration: 78f4770515141efb7f55f9b27c49dda95319c3a8 + React-rendererconsistency: f7baab26c6d0cd5b2eb7afcecfd2d8b957017b18 + React-renderercss: bdd2f83a4a054c3e4321fd61305c202b848e471b + React-rendererdebug: 9f8865ee038127a9d99d4b034c9da4935d204993 + React-rncore: f7438473c4c71ee1963fb06a8635bb96013c9e1c + React-RuntimeApple: 4d2ab9f72b9193da86eceded128a67254fc18aeb + React-RuntimeCore: 5fd73030438d094975ca0f549d162dd97746ae38 + React-runtimeexecutor: 17c70842d5e611130cb66f91e247bc4a609c3508 + React-RuntimeHermes: 3c88e6e1ea7ea0899dcffc77c10d61ea46688cfd + React-runtimescheduler: 024500621c7c93d65371498abb4ee26d34f5d47d + React-Sandbox: e3cf3c955559ed9f0bf014b29dce1e94600cd790 + React-timing: c3c923df2b86194e1682e01167717481232f1dc7 + React-utils: 9154a037543147e1c24098f1a48fc8472602c092 + ReactAppDependencyProvider: afd905e84ee36e1678016ae04d7370c75ed539be + ReactCodegen: 06bf9ae2e01a2416250cf5e44e4a06b1c9ea201b + ReactCommon: 17fd88849a174bf9ce45461912291aca711410fc + SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 + Yoga: daa1e4de4b971b977b23bc842aaa3e135324f1f3 + +PODFILE CHECKSUM: f57c2d8a159b8fcf2a742eb959389b3a31be7cad + +COCOAPODS: 1.16.2 diff --git a/apps/p2p-chat/jest.config.js b/apps/p2p-chat/jest.config.js new file mode 100644 index 0000000..f9902db --- /dev/null +++ b/apps/p2p-chat/jest.config.js @@ -0,0 +1,7 @@ +module.exports = { + preset: 'react-native', + transformIgnorePatterns: [ + 'node_modules/(?!(react-native|@react-native|@react-native-community|@callstack/react-native-sandbox|react-native-toast-message|react-native-reanimated)/)', + ], + setupFilesAfterEnv: ['/../../jest.setup.js'], +} diff --git a/apps/p2p-chat/metro.config.js b/apps/p2p-chat/metro.config.js new file mode 100644 index 0000000..a4d147a --- /dev/null +++ b/apps/p2p-chat/metro.config.js @@ -0,0 +1,24 @@ +const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config') +const path = require('path') + +const projectRoot = __dirname +const workspaceRoot = path.resolve(projectRoot, '../..') + +/** + * Metro configuration + * https://reactnative.dev/docs/metro + * + * @type {import('@react-native/metro-config').MetroConfig} + */ +const config = { + watchFolders: [workspaceRoot], + resolver: { + nodeModulesPaths: [ + path.resolve(projectRoot, 'node_modules'), + path.resolve(workspaceRoot, 'node_modules'), + ], + disableHierarchicalLookup: true, + }, +} + +module.exports = mergeConfig(getDefaultConfig(projectRoot), config) diff --git a/apps/p2p-chat/package.json b/apps/p2p-chat/package.json new file mode 100644 index 0000000..56960c1 --- /dev/null +++ b/apps/p2p-chat/package.json @@ -0,0 +1,32 @@ +{ + "name": "@apps/p2p-chat", + "version": "0.0.1", + "private": true, + "scripts": { + "android": "react-native run-android", + "ios": "react-native run-ios", + "start": "react-native start" + }, + "dependencies": { + "react": "19.1.0", + "react-native": "0.80.1", + "react-native-toast-message": "^2.3.2", + "@callstack/react-native-sandbox": "workspace:*" + }, + "devDependencies": { + "@babel/core": "^7.25.2", + "@babel/preset-env": "^7.25.3", + "@babel/runtime": "^7.25.0", + "@react-native-community/cli": "18.0.0", + "@react-native-community/cli-platform-android": "18.0.0", + "@react-native-community/cli-platform-ios": "18.0.0", + "@react-native/babel-preset": "0.80.1", + "@react-native/eslint-config": "0.80.1", + "@react-native/metro-config": "0.80.1", + "@react-native/typescript-config": "0.80.1", + "react-test-renderer": "19.1.0" + }, + "engines": { + "node": ">=18" + } +} \ No newline at end of file diff --git a/apps/p2p-chat/src/App.tsx b/apps/p2p-chat/src/App.tsx new file mode 100644 index 0000000..7bc1ae5 --- /dev/null +++ b/apps/p2p-chat/src/App.tsx @@ -0,0 +1,66 @@ +import React, {useRef} from 'react' +import {Dimensions, SafeAreaView, StatusBar} from 'react-native' + +import {ChatCarousel} from './components' +import {useChatInstances, useScrollColorInterpolation} from './hooks' +import {MessageHandler} from './services' +import {carouselStyles} from './styles' + +const {width: screenWidth} = Dimensions.get('window') + +const App = () => { + const { + chatInstances, + currentIndex, + setCurrentIndex, + friendshipTrigger, + friendshipManager, + addChatInstance, + removeChatInstance, + triggerFriendshipUpdate, + } = useChatInstances() + + const sandboxRefs = useRef>({}) + + const messageHandler = new MessageHandler( + chatInstances, + friendshipManager, + sandboxRefs, + triggerFriendshipUpdate + ) + + // Use the scroll color interpolation hook + const {currentBackgroundColor, onScroll} = useScrollColorInterpolation({ + chatInstances, + scrollStep: screenWidth, // Now each slide takes full screen width + onIndexChange: setCurrentIndex, + }) + + return ( + + + + + + ) +} + +export default App diff --git a/apps/p2p-chat/src/ChatApp.tsx b/apps/p2p-chat/src/ChatApp.tsx new file mode 100644 index 0000000..f1106be --- /dev/null +++ b/apps/p2p-chat/src/ChatApp.tsx @@ -0,0 +1,151 @@ +import React, {useCallback, useState} from 'react' +import {LogBox, StatusBar, View} from 'react-native' + +import { + FriendRequestsList, + MessageInput, + MessagesList, + TargetSelector, +} from './components' +import { + useCommunication, + useFriendRequests, + useMessages, + useTargetSelection, +} from './hooks' +import {commonStyles} from './styles' +import {ChatAppProps, MessageData} from './types' + +// Utility function to create subtle background from vibrant color +const createSubtleBackground = (vibrantColor: string): string => { + // Convert hex to RGB + const hex = vibrantColor.replace('#', '') + const r = parseInt(hex.substr(0, 2), 16) + const g = parseInt(hex.substr(2, 2), 16) + const b = parseInt(hex.substr(4, 2), 16) + + // Create a very light version (90% white + 10% color) + const lightR = Math.round(255 * 0.9 + r * 0.1) + const lightG = Math.round(255 * 0.9 + g * 0.1) + const lightB = Math.round(255 * 0.9 + b * 0.1) + + return `rgb(${lightR}, ${lightG}, ${lightB})` +} + +LogBox.ignoreAllLogs() + +const ChatApp: React.FC = ({ + userId, + userName, + targetOptions, + potentialFriends, + pendingRequests, + backgroundColor, +}) => { + const [, setIsConnected] = useState(false) + + const {sendMessage, sendConnectionMessage} = useCommunication({ + userName, + userId, + onMessage: handleIncomingMessage, + onConnectionEstablished: () => { + const allTargets = [ + ...targetOptions, + ...potentialFriends.map(pf => pf.id), + ] + sendConnectionMessage(allTargets) + }, + }) + + const {selectedTarget, setSelectedTarget} = useTargetSelection({ + targetOptions, + potentialFriends, + }) + + const { + messages, + inputText, + setInputText, + sendChatMessage, + handleIncomingMessage: handleMessageIncoming, + } = useMessages({ + userId, + userName, + onSendMessage: (message: MessageData) => { + const success = sendMessage(message) + if (success) { + setIsConnected(true) + } + return success + }, + }) + + const {respondToFriendRequest, handleFriendMessage, sendFriendRequest} = + useFriendRequests({ + userName, + onSendMessage: sendMessage, + }) + + function handleIncomingMessage(data: MessageData) { + console.log(`[${userName}] Processing message type: ${data.type}`) + + handleMessageIncoming(data) + handleFriendMessage(data) + if ( + data.type === 'chat_message' || + data.type === 'connection_established' + ) { + setIsConnected(true) + } + } + + const handleSendMessage = useCallback(() => { + sendChatMessage(selectedTarget) + }, [sendChatMessage, selectedTarget]) + + const handleTargetSelect = useCallback( + (target: string) => { + setSelectedTarget(target) + }, + [setSelectedTarget] + ) + + const handleSendFriendRequest = useCallback( + (targetId: string) => { + sendFriendRequest(targetId) + }, + [sendFriendRequest] + ) + + const subtleBackground = createSubtleBackground(backgroundColor) + + return ( + + + + + + + + + + + + ) +} + +export default ChatApp diff --git a/apps/p2p-chat/src/components/ChatCarousel.tsx b/apps/p2p-chat/src/components/ChatCarousel.tsx new file mode 100644 index 0000000..2c941fd --- /dev/null +++ b/apps/p2p-chat/src/components/ChatCarousel.tsx @@ -0,0 +1,258 @@ +import SandboxReactNativeView from '@callstack/react-native-sandbox' +import React, {useCallback, useEffect, useRef} from 'react' +import { + Dimensions, + NativeScrollEvent, + NativeSyntheticEvent, + ScrollView, + Text, + TouchableOpacity, + View, +} from 'react-native' + +import {ChatMeta, MAX_CHAT_INSTANCES} from '../constants' +import {FriendshipManager, MessageHandler} from '../services' +import {carouselStyles} from '../styles' +import {getChatHelpers} from '../utils/chatHelpers' + +// Individual Chat Instance Component +interface ChatInstanceViewProps { + chat: ChatMeta + friendshipTrigger: number + friendshipManager: FriendshipManager + messageHandler: MessageHandler + sandboxRefs: React.RefObject> + chatInstances: ChatMeta[] + onRemoveChatInstance: (chatId: string) => void +} + +const ChatInstanceView: React.FC = ({ + chat, + friendshipTrigger, + friendshipManager, + messageHandler, + sandboxRefs, + chatInstances, + onRemoveChatInstance, +}) => { + const { + getTargetOptions, + getPotentialFriends, + getPendingRequests, + getFriends, + } = getChatHelpers(chatInstances, friendshipManager) + + // Get list of friend IDs for allowedOrigins + const allowedOrigins = getFriends(chat.id).map(friend => friend.id) + + return ( + + + + + {chat.id} + + + onRemoveChatInstance(chat.id)} + disabled={chatInstances.length <= 1}> + + × + + + + + + { + if (ref) { + sandboxRefs.current[chat.id] = ref + console.log( + `[Host] Registered sandbox ref for ${chat.id}. Active refs:`, + Object.keys(sandboxRefs.current) + ) + } else { + console.log(`[Host] Removing sandbox ref for ${chat.id}`) + delete sandboxRefs.current[chat.id] + } + }} + origin={chat.id} + componentName="ChatApp" + initialProperties={{ + userId: chat.id, + userName: chat.userName, + targetOptions: getTargetOptions(chat.id), + potentialFriends: getPotentialFriends(chat.id), + pendingRequests: getPendingRequests(chat.id), + backgroundColor: chat.backgroundColor, + friendshipTrigger: friendshipTrigger, + }} + onError={messageHandler.handleChatError(chat.userName)} + onMessage={messageHandler.handleChatMessage(chat.id)} + allowedOrigins={allowedOrigins} + style={carouselStyles.sandbox} + /> + + + + ) +} + +// Add Chat Component +interface AddChatViewProps { + chatInstances: ChatMeta[] + onAddChatInstance: () => void +} + +const AddChatView: React.FC = ({ + chatInstances, + onAddChatInstance, +}) => { + const canAddMore = chatInstances.length < MAX_CHAT_INSTANCES + + return ( + + + + + + + + + Add Chat + + + {chatInstances.length} / {MAX_CHAT_INSTANCES} + + + + + ) +} + +interface ChatCarouselProps { + chatInstances: ChatMeta[] + currentIndex: number + friendshipTrigger: number + friendshipManager: FriendshipManager + sandboxRefs: React.RefObject> + messageHandler: MessageHandler + onScroll: (event: NativeSyntheticEvent) => void + onRemoveChatInstance: (chatId: string) => void + onAddChatInstance: () => void +} + +export const ChatCarousel: React.FC = ({ + chatInstances, + currentIndex, + friendshipTrigger, + friendshipManager, + sandboxRefs, + messageHandler, + onScroll, + onRemoveChatInstance, + onAddChatInstance, +}) => { + const scrollViewRef = useRef(null) + + // Function to scroll to specific chat + const scrollToChat = useCallback( + (targetChatId: string) => { + const targetIndex = chatInstances.findIndex( + chat => chat.id === targetChatId + ) + if (targetIndex !== -1 && scrollViewRef.current) { + // Each slide now takes full screen width for proper paging + const {width: screenWidth} = Dimensions.get('window') + const scrollX = targetIndex * screenWidth + + scrollViewRef.current.scrollTo({ + x: scrollX, + y: 0, + animated: true, + }) + } + }, + [chatInstances] + ) + + // Expose scroll function to messageHandler + useEffect(() => { + if ( + messageHandler && + typeof messageHandler.setScrollToChat === 'function' + ) { + messageHandler.setScrollToChat(scrollToChat) + } + }, [messageHandler, chatInstances, scrollToChat]) + + return ( + <> + + + {chatInstances.map(chat => ( + + ))} + + + + + + + {[...chatInstances, {id: 'add-button'}].map((_, index) => ( + + ))} + + + + + 💬 Multi-Instance P2P Chat Demo{'\n'} + Each chat runs in an isolated React Native sandbox + + + + ) +} diff --git a/apps/p2p-chat/src/components/FriendRequestsList.tsx b/apps/p2p-chat/src/components/FriendRequestsList.tsx new file mode 100644 index 0000000..7c97403 --- /dev/null +++ b/apps/p2p-chat/src/components/FriendRequestsList.tsx @@ -0,0 +1,99 @@ +import React from 'react' +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native' + +import { + buttonStyles, + colors, + commonStyles, + spacing, + typography, +} from '../styles/common' +import {FriendAction, FriendRequest} from '../types/friends' + +interface FriendRequestsListProps { + pendingRequests: FriendRequest[] + onRespondToRequest: (requestId: string, action: FriendAction) => void +} + +export const FriendRequestsList: React.FC = ({ + pendingRequests, + onRespondToRequest, +}) => { + if (pendingRequests.length === 0) { + return null + } + + return ( + + Friend Requests + {pendingRequests.map(request => ( + + + {request.from} wants to be friends + + + onRespondToRequest(request.id, 'accept')}> + Accept + + onRespondToRequest(request.id, 'reject')}> + Reject + + + + ))} + + ) +} + +const styles = StyleSheet.create({ + container: { + padding: spacing.md, + borderBottomWidth: 1, + borderBottomColor: colors.border, + backgroundColor: 'rgba(255,255,255,0.95)', + }, + title: { + fontSize: typography.sizes.lg, + fontWeight: typography.weights.semibold, + color: colors.text.primary, + marginBottom: spacing.sm, + }, + friendRequest: { + ...commonStyles.row, + justifyContent: 'space-between', + backgroundColor: '#f0f0f0', + padding: spacing.sm + 2, // 10px + ...commonStyles.rounded, + marginBottom: spacing.sm, + ...commonStyles.border, + }, + friendRequestText: { + flex: 1, + fontSize: typography.sizes.md + 1, // 13px + color: colors.text.primary, + marginRight: spacing.sm + 2, // 10px + }, + buttonContainer: { + flexDirection: 'row', + }, + actionButton: { + paddingHorizontal: spacing.md, + paddingVertical: 6, + marginLeft: spacing.sm, + }, + buttonText: { + fontSize: typography.sizes.md, + }, +}) diff --git a/apps/p2p-chat/src/components/MessageInput.tsx b/apps/p2p-chat/src/components/MessageInput.tsx new file mode 100644 index 0000000..26b4646 --- /dev/null +++ b/apps/p2p-chat/src/components/MessageInput.tsx @@ -0,0 +1,86 @@ +import React from 'react' +import {StyleSheet, Text, TextInput, TouchableOpacity, View} from 'react-native' + +import {buttonStyles, colors, spacing, typography} from '../styles/common' + +interface MessageInputProps { + inputText: string + selectedTarget: string + onInputChange: (text: string) => void + onSendMessage: () => void +} + +export const MessageInput: React.FC = ({ + inputText, + selectedTarget, + onInputChange, + onSendMessage, +}) => { + const canSend = inputText.trim() && selectedTarget.trim() + + const handleSubmit = () => { + if (canSend) { + onSendMessage() + } + } + + return ( + + + + Send + + + ) +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + padding: spacing.md, + borderTopWidth: 1, + borderTopColor: colors.border, + backgroundColor: 'rgba(255,255,255,0.95)', + }, + textInput: { + flex: 1, + borderWidth: 1, + borderColor: 'rgba(0,0,0,0.2)', + borderRadius: 18, + paddingHorizontal: spacing.md, + paddingVertical: spacing.sm, + marginRight: spacing.sm, + maxHeight: 80, + backgroundColor: colors.surface, + fontSize: typography.sizes.lg, + }, + sendButton: { + borderRadius: 18, + paddingHorizontal: spacing.lg, + paddingVertical: spacing.sm + 2, // 10px + }, + sendButtonText: { + fontSize: typography.sizes.lg, + }, +}) diff --git a/apps/p2p-chat/src/components/MessagesList.tsx b/apps/p2p-chat/src/components/MessagesList.tsx new file mode 100644 index 0000000..b1d26ab --- /dev/null +++ b/apps/p2p-chat/src/components/MessagesList.tsx @@ -0,0 +1,159 @@ +import React, {useEffect, useRef} from 'react' +import {ScrollView, StyleSheet, Text, View} from 'react-native' + +import {colors, commonStyles, spacing, typography} from '../styles/common' +import {Message} from '../types' + +interface MessagesListProps { + messages: Message[] + selectedTarget: string +} + +export const MessagesList: React.FC = ({ + messages, + selectedTarget, +}) => { + const scrollRef = useRef(null) + + useEffect(() => { + // Auto-scroll to bottom when new messages arrive + if (messages.length > 0) { + setTimeout(() => { + scrollRef.current?.scrollToEnd({animated: true}) + }, 100) + } + }, [messages]) + + const formatTime = (timestamp: number) => { + return new Date(timestamp).toLocaleTimeString([], { + hour: '2-digit', + minute: '2-digit', + }) + } + + return ( + + {messages.length === 0 && ( + + + {selectedTarget + ? `Send a message to start chatting with ${selectedTarget}!` + : 'Select or enter a target to start messaging!'} + + + )} + + {messages.map(message => ( + + {message.type === 'error' && ( + + ⚠️ + + )} + + {message.text} + + + {message.sender} • {formatTime(message.timestamp)} + + + ))} + + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + padding: spacing.sm, + backgroundColor: 'rgba(255,255,255,0.3)', + }, + emptyState: { + flex: 1, + ...commonStyles.centered, + padding: spacing.xl, + }, + emptyText: { + fontSize: typography.sizes.md + 1, // 13px + color: colors.text.secondary, + textAlign: 'center', + fontStyle: 'italic', + }, + messageBubble: { + marginVertical: 3, + padding: spacing.sm + 2, // 10px + borderRadius: 14, + maxWidth: '80%', + }, + sentMessage: { + alignSelf: 'flex-end', + backgroundColor: colors.primary, + }, + receivedMessage: { + alignSelf: 'flex-start', + backgroundColor: 'rgba(255,255,255,0.95)', + ...commonStyles.border, + }, + errorMessage: { + alignSelf: 'flex-start', + backgroundColor: '#ffebee', // Light red background + borderWidth: 1, + borderColor: colors.error, // Red border + }, + errorIcon: { + alignSelf: 'flex-start', + marginLeft: 5, + marginTop: -5, + backgroundColor: colors.error, + borderRadius: 8, + padding: 2, + }, + errorIconText: { + fontSize: typography.sizes.lg, + color: colors.text.white, + }, + messageText: { + fontSize: typography.sizes.lg, + color: colors.text.primary, + marginBottom: 3, + }, + sentMessageText: { + color: colors.text.white, + }, + errorMessageText: { + color: '#d32f2f', // Darker red for error text + }, + messageTime: { + fontSize: typography.sizes.sm, + color: colors.text.secondary, + fontWeight: typography.weights.medium, + }, + sentMessageTime: { + color: 'rgba(255,255,255,0.8)', + }, + errorMessageTime: { + color: colors.error, // Red for error time + }, +}) diff --git a/apps/p2p-chat/src/components/TargetSelector.tsx b/apps/p2p-chat/src/components/TargetSelector.tsx new file mode 100644 index 0000000..fa6783a --- /dev/null +++ b/apps/p2p-chat/src/components/TargetSelector.tsx @@ -0,0 +1,146 @@ +import React from 'react' +import { + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, +} from 'react-native' + +import {colors, commonStyles, spacing, typography} from '../styles' +import {PotentialFriend} from '../types' + +interface TargetSelectorProps { + targetOptions: string[] + potentialFriends: PotentialFriend[] + selectedTarget: string + onTargetSelect: (target: string) => void + onSendFriendRequest: (targetId: string) => void +} + +export const TargetSelector: React.FC = ({ + targetOptions, + potentialFriends, + selectedTarget, + onTargetSelect, + onSendFriendRequest, +}) => { + const allPossibleTargets = [ + ...targetOptions, // Current friends + ...potentialFriends.map(pf => pf.id), // Potential friends + ] + + const handleTargetPress = (target: string) => { + if (targetOptions.includes(target)) { + // This is a friend - select for messaging + onTargetSelect(target) + } else { + // This is a potential friend - send friend request + onSendFriendRequest(target) + } + } + + return ( + <> + {allPossibleTargets.length > 0 ? ( + + Friends & Available Users: + + {allPossibleTargets.map(target => { + const isFriend = targetOptions.includes(target) + const isSelected = selectedTarget === target + return ( + handleTargetPress(target)}> + + {isFriend ? '👫' : '👥'} {target} + {!isFriend && ( + (tap to add) + )} + + + ) + })} + + + ) : ( + + + No friends or available users to chat with. + + + )} + + ) +} + +const styles = StyleSheet.create({ + targetSelector: { + padding: spacing.md, + borderBottomWidth: 1, + borderBottomColor: colors.border, + backgroundColor: 'rgba(255,255,255,0.9)', + }, + targetLabel: { + fontSize: typography.sizes.md, + fontWeight: typography.weights.semibold, + color: colors.text.secondary, + marginBottom: 6, + }, + targetButton: { + backgroundColor: '#f0f0f0', + paddingHorizontal: spacing.md, + paddingVertical: 6, + borderRadius: 12, + marginRight: spacing.sm, + ...commonStyles.border, + }, + selectedTargetButton: { + backgroundColor: colors.primary, + borderColor: colors.primary, + }, + targetButtonText: { + fontSize: typography.sizes.md, + fontWeight: typography.weights.medium, + color: colors.text.primary, + }, + selectedTargetButtonText: { + color: colors.text.white, + fontWeight: typography.weights.semibold, + }, + potentialFriendButton: { + backgroundColor: '#fff3cd', + borderColor: '#ffc107', + }, + potentialFriendButtonText: { + color: '#856404', + }, + actionHint: { + fontSize: typography.sizes.sm, + fontStyle: 'italic', + opacity: 0.8, + }, + noTargetsContainer: { + padding: spacing.md, + borderBottomWidth: 1, + borderBottomColor: colors.border, + backgroundColor: 'rgba(255,193,7,0.1)', + }, + noTargetsText: { + fontSize: typography.sizes.md, + color: colors.warning, + textAlign: 'center', + fontStyle: 'italic', + }, +}) diff --git a/apps/p2p-chat/src/components/index.ts b/apps/p2p-chat/src/components/index.ts new file mode 100644 index 0000000..b754d58 --- /dev/null +++ b/apps/p2p-chat/src/components/index.ts @@ -0,0 +1,5 @@ +export {ChatCarousel} from './ChatCarousel' +export {FriendRequestsList} from './FriendRequestsList' +export {MessageInput} from './MessageInput' +export {MessagesList} from './MessagesList' +export {TargetSelector} from './TargetSelector' diff --git a/apps/p2p-chat/src/constants.ts b/apps/p2p-chat/src/constants.ts new file mode 100644 index 0000000..47a4035 --- /dev/null +++ b/apps/p2p-chat/src/constants.ts @@ -0,0 +1,25 @@ +import {Dimensions} from 'react-native' + +const {width: screenWidth} = Dimensions.get('window') + +// Carousel slide dimensions +export const CHAT_WIDTH = screenWidth - 32 // Account for container margins +export const SLIDE_MARGIN = 8 // Horizontal margin between slides + +export const USER_THEMES = [ + {name: 'Alice', color: '#667eea'}, + {name: 'Bob', color: '#f093fb'}, + {name: 'Charlie', color: '#4facfe'}, + {name: 'Diana', color: '#43e97b'}, + {name: 'Eve', color: '#fa709a'}, + {name: 'Frank', color: '#a8edea'}, +] as const + +export const MAX_CHAT_INSTANCES = USER_THEMES.length +export const MIN_CHAT_INSTANCES = 1 + +export interface ChatMeta { + id: string + userName: string + backgroundColor: string +} diff --git a/apps/p2p-chat/src/hooks/index.ts b/apps/p2p-chat/src/hooks/index.ts new file mode 100644 index 0000000..f8a5339 --- /dev/null +++ b/apps/p2p-chat/src/hooks/index.ts @@ -0,0 +1,6 @@ +export {useChatInstances} from './useChatInstances' +export {useCommunication} from './useCommunication' +export {useFriendRequests} from './useFriendRequests' +export {useMessages} from './useMessages' +export {useScrollColorInterpolation} from './useScrollColorInterpolation' +export {useTargetSelection} from './useTargetSelection' diff --git a/apps/p2p-chat/src/hooks/useChatInstances.ts b/apps/p2p-chat/src/hooks/useChatInstances.ts new file mode 100644 index 0000000..fecc0aa --- /dev/null +++ b/apps/p2p-chat/src/hooks/useChatInstances.ts @@ -0,0 +1,70 @@ +import {useCallback, useRef, useState} from 'react' + +import {ChatMeta, MAX_CHAT_INSTANCES, USER_THEMES} from '../constants' +import {FriendshipManager} from '../services' +import {createChatInstance} from '../utils/chatHelpers' + +export const useChatInstances = () => { + const [chatInstances, setChatInstances] = useState([ + createChatInstance(USER_THEMES[0].name, USER_THEMES[0].color), + createChatInstance(USER_THEMES[1].name, USER_THEMES[1].color), + ]) + const [currentIndex, setCurrentIndex] = useState(0) + const [friendshipTrigger, setFriendshipTrigger] = useState(0) + const friendshipManager = useRef(new FriendshipManager()).current + + const addChatInstance = useCallback(() => { + if (chatInstances.length >= MAX_CHAT_INSTANCES) { + console.log('Maximum number of chat instances reached') + return + } + + // Find the next available preset user + const usedNames = new Set(chatInstances.map(chat => chat.userName)) + const availableUser = USER_THEMES.find(user => !usedNames.has(user.name)) + + if (!availableUser) { + console.log('No more preset users available') + return + } + + const newInstance = createChatInstance( + availableUser.name, + availableUser.color + ) + setChatInstances(prev => [...prev, newInstance]) + + console.log(`[Host] Added new chat instance: ${newInstance.userName}`) + }, [chatInstances]) + + const removeChatInstance = useCallback( + (chatId: string) => { + if (chatInstances.length <= 1) { + console.log('Cannot remove the last chat instance') + return + } + + setChatInstances(prev => prev.filter(chat => chat.id !== chatId)) + console.log(`[Host] Removed chat instance: ${chatId}`) + + // Trigger friendship updates since instances changed + setFriendshipTrigger(prev => prev + 1) + }, + [chatInstances.length] + ) + + const triggerFriendshipUpdate = useCallback(() => { + setFriendshipTrigger(prev => prev + 1) + }, []) + + return { + chatInstances, + currentIndex, + setCurrentIndex, + friendshipTrigger, + friendshipManager, + addChatInstance, + removeChatInstance, + triggerFriendshipUpdate, + } +} diff --git a/apps/p2p-chat/src/hooks/useColorAnimation.ts b/apps/p2p-chat/src/hooks/useColorAnimation.ts new file mode 100644 index 0000000..a8e68c8 --- /dev/null +++ b/apps/p2p-chat/src/hooks/useColorAnimation.ts @@ -0,0 +1,46 @@ +import {useCallback, useState} from 'react' +import {NativeScrollEvent, NativeSyntheticEvent} from 'react-native' + +import {ChatMeta} from '../constants' +import {calculateBackgroundColor, calculateSlideIndex} from '../utils' + +interface UseScrollColorInterpolationProps { + chatInstances: ChatMeta[] + scrollStep: number // Width of each scroll step (e.g., screen width for full-width slides) + onIndexChange: (index: number) => void +} + +export const useScrollColorInterpolation = ({ + chatInstances, + scrollStep, + onIndexChange, +}: UseScrollColorInterpolationProps) => { + // State for smooth color interpolation + const [currentBackgroundColor, setCurrentBackgroundColor] = useState( + chatInstances[0]?.backgroundColor || '#667eea' + ) + + const onScroll = useCallback( + (event: NativeSyntheticEvent) => { + const scrollX = event.nativeEvent.contentOffset.x + + // Update current index + const slideIndex = calculateSlideIndex(scrollX, scrollStep) + onIndexChange(slideIndex) + + // Calculate and update background color + const backgroundColor = calculateBackgroundColor( + scrollX, + scrollStep, + chatInstances + ) + setCurrentBackgroundColor(backgroundColor) + }, + [chatInstances, scrollStep, onIndexChange] + ) + + return { + currentBackgroundColor, + onScroll, + } +} diff --git a/apps/p2p-chat/src/hooks/useCommunication.ts b/apps/p2p-chat/src/hooks/useCommunication.ts new file mode 100644 index 0000000..93f0710 --- /dev/null +++ b/apps/p2p-chat/src/hooks/useCommunication.ts @@ -0,0 +1,104 @@ +import {useCallback, useEffect} from 'react' + +import {MessageData} from '../types' + +// Global function declarations for sandbox environment +declare global { + var setOnMessage: (callback: (data: any) => void) => void + var postMessage: (message: any, targetOrigin?: string) => void +} + +interface UseCommunicationProps { + userName: string + userId: string + onMessage: (data: MessageData) => void + onConnectionEstablished?: () => void +} + +export const useCommunication = ({ + userName, + userId, + onMessage, + onConnectionEstablished, +}: UseCommunicationProps) => { + useEffect(() => { + // Set up message listener for P2P communication + if (global.setOnMessage) { + console.log( + `[${userName}] global.setOnMessage is available, setting up listener` + ) + global.setOnMessage((data: any) => { + console.log(`[${userName}] 🔥 MESSAGE RECEIVED:`, data) + + if (!data || !data.type) { + console.warn(`[${userName}] Received message without type:`, data) + return + } + + console.log(`[${userName}] Processing message type: ${data.type}`) + onMessage(data) + }) + + console.log(`[${userName}] ✅ Message listener setup complete`) + } else { + console.warn(`[${userName}] ❌ global.setOnMessage is not available!`) + console.log( + `[${userName}] Available global functions:`, + Object.keys(global).filter( + key => typeof (global as any)[key] === 'function' + ) + ) + } + + // Send initial connection message if callback provided + if (onConnectionEstablished) { + onConnectionEstablished() + } + + // Announce readiness + console.log( + `[${userName}] 📢 Sandbox initialization complete and ready to receive messages` + ) + }, [userName, onMessage, onConnectionEstablished]) + + const sendMessage = useCallback( + (message: MessageData, targetOrigin?: string) => { + if (global.postMessage) { + try { + global.postMessage(message, targetOrigin) + return true + } catch (error) { + console.error(`[${userName}] Failed to send message:`, error) + return false + } + } + return false + }, + [userName] + ) + + const sendConnectionMessage = useCallback( + (targets: string[]) => { + if (global.postMessage && targets.length > 0) { + targets.forEach(targetId => { + global.postMessage!( + { + type: 'connection_established', + senderId: userId, + senderName: userName, + timestamp: Date.now(), + }, + targetId + ) + }) + } + }, + [userId, userName] + ) + + return { + sendMessage, + sendConnectionMessage, + isReady: !!global.postMessage, + } +} diff --git a/apps/p2p-chat/src/hooks/useFriendRequests.ts b/apps/p2p-chat/src/hooks/useFriendRequests.ts new file mode 100644 index 0000000..ea03c80 --- /dev/null +++ b/apps/p2p-chat/src/hooks/useFriendRequests.ts @@ -0,0 +1,107 @@ +import {useCallback, useState} from 'react' + +import {FriendAction, MessageData} from '../types' + +interface UseFriendRequestsProps { + userName: string + onSendMessage: (message: MessageData) => boolean +} + +export const useFriendRequests = ({ + userName, + onSendMessage, +}: UseFriendRequestsProps) => { + const [friendNotifications, setFriendNotifications] = useState([]) + + const clearNotification = useCallback((index: number) => { + setFriendNotifications(prev => prev.filter((_, i) => i !== index)) + }, []) + + const addNotification = useCallback((notification: string) => { + setFriendNotifications(prev => [...prev, notification]) + }, []) + + const sendFriendRequest = useCallback( + (targetId: string) => { + const success = onSendMessage({ + type: 'make_friend', + target: targetId, + timestamp: Date.now(), + }) + + if (success) { + console.log( + `[${userName}] Friend request sent to host for routing to ${targetId}` + ) + } + }, + [userName, onSendMessage] + ) + + const respondToFriendRequest = useCallback( + (requestId: string, action: FriendAction) => { + console.log( + `[${userName}] Responding to friend request ${requestId}: ${action}` + ) + + const success = onSendMessage({ + type: 'friend_response', + requestId, + action, + timestamp: Date.now(), + }) + + if (success) { + console.log(`[${userName}] Friend response sent to host`) + } + }, + [userName, onSendMessage] + ) + + const handleFriendMessage = useCallback( + (data: MessageData) => { + switch (data.type) { + case 'friend_request': { + if (data.fromName) { + console.log( + `[${userName}] 🚨 PROCESSING FRIEND REQUEST from ${data.fromName} (${data.from})` + ) + addNotification(`Friend request from ${data.fromName}`) + console.log(`[${userName}] Friend request notification added`) + } + break + } + + case 'friend_accepted': { + if (data.friendName) { + console.log( + `[${userName}] Friend request accepted by ${data.friendName}` + ) + addNotification(`${data.friendName} accepted your friend request!`) + } + break + } + + case 'friendship_established': { + if (data.friendName) { + console.log( + `[${userName}] Friendship established with ${data.friendName}` + ) + addNotification(`You are now friends with ${data.friendName}!`) + } + break + } + } + }, + [userName, addNotification] + ) + + return { + friendNotifications, + clearNotification, + addNotification, + sendFriendRequest, + respondToFriendRequest, + handleFriendMessage, + } +} diff --git a/apps/p2p-chat/src/hooks/useMessages.ts b/apps/p2p-chat/src/hooks/useMessages.ts new file mode 100644 index 0000000..67a8338 --- /dev/null +++ b/apps/p2p-chat/src/hooks/useMessages.ts @@ -0,0 +1,116 @@ +import {useCallback, useState} from 'react' + +import {Message, MessageData} from '../types' + +interface UseMessagesProps { + userId: string + userName: string + onSendMessage: (message: MessageData) => boolean +} + +export const useMessages = ({ + userId, + userName, + onSendMessage, +}: UseMessagesProps) => { + const [messages, setMessages] = useState([]) + const [inputText, setInputText] = useState('') + + const addMessage = useCallback((message: Message) => { + setMessages(prev => [...prev, message]) + }, []) + + const sendChatMessage = useCallback( + (target: string) => { + if (!inputText.trim() || !target.trim()) return + + const messageId = `${userId}_${Date.now()}` + const timestamp = Date.now() + + // Add to local messages + const newMessage: Message = { + id: messageId, + text: inputText.trim(), + sender: userName, + timestamp, + type: 'sent', + } + + addMessage(newMessage) + + // Send P2P message to selected target sandbox via host + const success = onSendMessage({ + type: 'chat_message', + messageId, + text: inputText.trim(), + senderId: userId, + senderName: userName, + timestamp, + target: target.trim(), + }) + + if (!success) { + // Add a local error message + const errorMessage: Message = { + id: `error_${Date.now()}`, + text: `Failed to send message: Communication error`, + sender: 'System', + timestamp: Date.now(), + type: 'error', + isError: true, + errorReason: 'send_failed', + } + addMessage(errorMessage) + } + + setInputText('') + }, + [inputText, userId, userName, onSendMessage, addMessage] + ) + + const handleIncomingMessage = useCallback( + (data: MessageData) => { + switch (data.type) { + case 'chat_message': { + if (data.messageId && data.text && data.senderName) { + const newMessage: Message = { + id: data.messageId, + text: data.text, + sender: data.senderName, + timestamp: data.timestamp, + type: 'received', + } + addMessage(newMessage) + } + break + } + + case 'message_error': { + if (data.errorText) { + const errorMessage: Message = { + id: `error_${Date.now()}`, + text: data.errorText, + sender: 'System', + timestamp: data.timestamp, + type: 'error', + isError: true, + errorReason: data.reason, + } + addMessage(errorMessage) + } + break + } + } + }, + [addMessage] + ) + + return { + messages, + inputText, + setInputText, + sendChatMessage, + handleIncomingMessage, + addMessage, + } +} diff --git a/apps/p2p-chat/src/hooks/useScrollColorInterpolation.ts b/apps/p2p-chat/src/hooks/useScrollColorInterpolation.ts new file mode 100644 index 0000000..a8e68c8 --- /dev/null +++ b/apps/p2p-chat/src/hooks/useScrollColorInterpolation.ts @@ -0,0 +1,46 @@ +import {useCallback, useState} from 'react' +import {NativeScrollEvent, NativeSyntheticEvent} from 'react-native' + +import {ChatMeta} from '../constants' +import {calculateBackgroundColor, calculateSlideIndex} from '../utils' + +interface UseScrollColorInterpolationProps { + chatInstances: ChatMeta[] + scrollStep: number // Width of each scroll step (e.g., screen width for full-width slides) + onIndexChange: (index: number) => void +} + +export const useScrollColorInterpolation = ({ + chatInstances, + scrollStep, + onIndexChange, +}: UseScrollColorInterpolationProps) => { + // State for smooth color interpolation + const [currentBackgroundColor, setCurrentBackgroundColor] = useState( + chatInstances[0]?.backgroundColor || '#667eea' + ) + + const onScroll = useCallback( + (event: NativeSyntheticEvent) => { + const scrollX = event.nativeEvent.contentOffset.x + + // Update current index + const slideIndex = calculateSlideIndex(scrollX, scrollStep) + onIndexChange(slideIndex) + + // Calculate and update background color + const backgroundColor = calculateBackgroundColor( + scrollX, + scrollStep, + chatInstances + ) + setCurrentBackgroundColor(backgroundColor) + }, + [chatInstances, scrollStep, onIndexChange] + ) + + return { + currentBackgroundColor, + onScroll, + } +} diff --git a/apps/p2p-chat/src/hooks/useTargetSelection.ts b/apps/p2p-chat/src/hooks/useTargetSelection.ts new file mode 100644 index 0000000..4d3a8d7 --- /dev/null +++ b/apps/p2p-chat/src/hooks/useTargetSelection.ts @@ -0,0 +1,50 @@ +import {useEffect, useMemo, useState} from 'react' + +import {PotentialFriend} from '../types' + +interface UseTargetSelectionProps { + targetOptions: string[] + potentialFriends: PotentialFriend[] +} + +export const useTargetSelection = ({ + targetOptions, + potentialFriends, +}: UseTargetSelectionProps) => { + const [selectedTarget, setSelectedTarget] = useState('') + + // Create a list of all possible targets (friends + potential friends) + const allPossibleTargets = useMemo( + () => [ + ...targetOptions, // Current friends + ...potentialFriends.map(pf => pf.id), // Potential friends + ], + [targetOptions, potentialFriends] + ) + + useEffect(() => { + // Update selected target if current one is no longer available + if ( + allPossibleTargets.length > 0 && + !allPossibleTargets.includes(selectedTarget) + ) { + setSelectedTarget(allPossibleTargets[0]) + } else if (allPossibleTargets.length === 0 && selectedTarget) { + // Keep the selected target even if no options available + // This allows users to manually type or remember target IDs + } + }, [targetOptions, potentialFriends, selectedTarget, allPossibleTargets]) + + // Initialize with first available target + useEffect(() => { + if (!selectedTarget && allPossibleTargets.length > 0) { + setSelectedTarget(allPossibleTargets[0]) + } + }, [allPossibleTargets, selectedTarget]) + + return { + selectedTarget, + setSelectedTarget, + allPossibleTargets, + } +} diff --git a/apps/p2p-chat/src/services/FriendshipManager.ts b/apps/p2p-chat/src/services/FriendshipManager.ts new file mode 100644 index 0000000..d61e6a0 --- /dev/null +++ b/apps/p2p-chat/src/services/FriendshipManager.ts @@ -0,0 +1,80 @@ +import {FriendRequest} from '../types' + +export class FriendshipManager { + private friendships = new Set() // "alice-bob" format (sorted) + private pendingRequests = new Map() + private requestCounter = 0 + + private createFriendshipKey(user1: string, user2: string): string { + return [user1, user2].sort().join('-') + } + + sendFriendRequest(from: string, to: string): string { + const requestId = `req_${++this.requestCounter}_${Date.now()}` + const request: FriendRequest = { + id: requestId, + from, + to, + timestamp: Date.now(), + status: 'pending', + } + + this.pendingRequests.set(requestId, request) + console.log( + `[FriendshipManager] Friend request sent: ${from} → ${to} (${requestId})` + ) + return requestId + } + + respondToRequest( + requestId: string, + action: 'accept' | 'reject' + ): FriendRequest | null { + const request = this.pendingRequests.get(requestId) + if (!request) { + console.warn(`[FriendshipManager] Request ${requestId} not found`) + return null + } + + request.status = action === 'accept' ? 'accepted' : 'rejected' + + if (action === 'accept') { + const friendshipKey = this.createFriendshipKey(request.from, request.to) + this.friendships.add(friendshipKey) + console.log( + `[FriendshipManager] Friendship established: ${request.from} ↔ ${request.to}` + ) + } + + this.pendingRequests.delete(requestId) + return request + } + + getFriends(userId: string): string[] { + const friends: string[] = [] + for (const friendship of this.friendships) { + const [user1, user2] = friendship.split('-') + if (user1 === userId) friends.push(user2) + if (user2 === userId) friends.push(user1) + } + return friends + } + + getPendingRequestsFor(userId: string): FriendRequest[] { + return Array.from(this.pendingRequests.values()).filter( + req => req.to === userId && req.status === 'pending' + ) + } + + hasPendingRequestBetween(user1: string, user2: string): boolean { + return Array.from(this.pendingRequests.values()).some( + req => + (req.from === user1 && req.to === user2) || + (req.from === user2 && req.to === user1) + ) + } + + areFriends(user1: string, user2: string): boolean { + return this.friendships.has(this.createFriendshipKey(user1, user2)) + } +} diff --git a/apps/p2p-chat/src/services/MessageHandler.ts b/apps/p2p-chat/src/services/MessageHandler.ts new file mode 100644 index 0000000..cc9416a --- /dev/null +++ b/apps/p2p-chat/src/services/MessageHandler.ts @@ -0,0 +1,191 @@ +import {ChatMeta} from '../constants' +import {FriendshipManager} from './FriendshipManager' + +export class MessageHandler { + private scrollToChat?: (chatId: string) => void + + constructor( + private chatInstances: ChatMeta[], + private friendshipManager: FriendshipManager, + private sandboxRefs: React.MutableRefObject>, + private triggerFriendshipUpdate: () => void + ) {} + + setScrollToChat = (scrollFunction: (chatId: string) => void) => { + this.scrollToChat = scrollFunction + } + + handleChatError = (chatId: string) => (error: any) => { + console.log(`[${chatId}] Error:`, error) + + // Send error message to sandbox for display in chat history + const errorMessage = { + type: 'message_error', + errorText: error.message || 'An error occurred', + reason: error.name || 'unknown_error', + timestamp: Date.now(), + } + + this.sendToSandbox(chatId, errorMessage) + } + + handleChatMessage = (chatId: string) => (data: any) => { + console.log(`[${chatId}] Received message from sandbox:`, data) + + if (!data.type) { + console.warn(`[Host] Message from ${chatId} missing type:`, data) + return + } + + switch (data.type) { + case 'make_friend': + this.handleMakeFriend(chatId, data) + break + case 'friend_response': + this.handleFriendResponse(chatId, data) + break + case 'chat_message': + this.handleForwardMessage(chatId, data) + break + default: + console.log(`[Host] Unknown message type from ${chatId}:`, data.type) + } + } + + private handleMakeFriend(chatId: string, data: any) { + const {target} = data + if (!target) { + console.warn(`[Host] make_friend message from ${chatId} missing target`) + return + } + + const targetInstance = this.chatInstances.find(inst => inst.id === target) + if (!targetInstance) { + console.warn( + `[Host] Target ${target} not found for friend request from ${chatId}` + ) + return + } + + if (this.friendshipManager.areFriends(chatId, target)) { + console.log(`[Host] ${chatId} and ${target} are already friends`) + return + } + + if (this.friendshipManager.hasPendingRequestBetween(chatId, target)) { + console.log( + `[Host] Pending friend request already exists between ${chatId} and ${target}` + ) + return + } + + const requestId = this.friendshipManager.sendFriendRequest(chatId, target) + + // Automatically scroll to target chat to make it easier to accept the invite + if (this.scrollToChat) { + setTimeout(() => { + this.scrollToChat!(target) + }, 100) // Small delay for UX + } + + setTimeout(() => { + const hostMessage = { + type: 'friend_request', + from: chatId, + fromName: + this.chatInstances.find(inst => inst.id === chatId)?.userName || + chatId, + requestId, + timestamp: Date.now(), + } + + this.sendToSandbox(target, hostMessage) + }, 500) + } + + private handleFriendResponse(chatId: string, data: any) { + const {requestId, action} = data + if (!requestId || !action) { + console.warn( + `[Host] friend_response from ${chatId} missing requestId or action` + ) + return + } + + const request = this.friendshipManager.respondToRequest(requestId, action) + if (!request) return + + this.triggerFriendshipUpdate() + + if (action === 'accept') { + // Notify the original requester + const acceptMessage = { + type: 'friend_accepted', + friend: chatId, + friendName: + this.chatInstances.find(inst => inst.id === chatId)?.userName || + chatId, + timestamp: Date.now(), + } + this.sendToSandbox(request.from, acceptMessage) + + // Notify both parties about established friendship + const friendshipMessage = { + type: 'friendship_established', + friendName: '', + timestamp: Date.now(), + } + + this.sendToSandbox(request.from, { + ...friendshipMessage, + friendName: + this.chatInstances.find(inst => inst.id === chatId)?.userName || + chatId, + }) + + this.sendToSandbox(chatId, { + ...friendshipMessage, + friendName: + this.chatInstances.find(inst => inst.id === request.from)?.userName || + request.from, + }) + } + } + + private handleForwardMessage(senderId: string, data: any) { + const {target, messageId, text, senderName, timestamp} = data + + if (!target || !messageId || !text || !senderName) { + console.warn( + `[Host] chat_message from ${senderId} missing required fields` + ) + return + } + + const forwardedMessage = { + type: 'chat_message', + messageId, + text, + senderId, + senderName, + timestamp, + } + + // Message will be blocked at native level if not allowed + this.sendToSandbox(target, forwardedMessage) + } + + private sendToSandbox(targetId: string, message: any) { + const targetRef = this.sandboxRefs.current[targetId] + if (targetRef) { + try { + targetRef.postMessage(message) + console.log(`[Host] Message sent to ${targetId}:`, message.type) + } catch (error) { + console.error(`[Host] Error sending message to ${targetId}:`, error) + } + } else { + console.error(`[Host] Target ref for ${targetId} not found`) + } + } +} diff --git a/apps/p2p-chat/src/services/index.ts b/apps/p2p-chat/src/services/index.ts new file mode 100644 index 0000000..4243d9b --- /dev/null +++ b/apps/p2p-chat/src/services/index.ts @@ -0,0 +1,2 @@ +export {FriendshipManager} from './FriendshipManager' +export {MessageHandler} from './MessageHandler' diff --git a/apps/p2p-chat/src/styles/carousel.ts b/apps/p2p-chat/src/styles/carousel.ts new file mode 100644 index 0000000..4c16c2f --- /dev/null +++ b/apps/p2p-chat/src/styles/carousel.ts @@ -0,0 +1,177 @@ +import {Dimensions, StyleSheet} from 'react-native' + +import {CHAT_WIDTH, SLIDE_MARGIN} from '../constants' + +const {width: screenWidth} = Dimensions.get('window') + +export const carouselStyles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: 'transparent', + }, + carouselContainer: { + flex: 1, + }, + carousel: { + flex: 1, + backgroundColor: 'transparent', + }, + carouselContent: { + paddingHorizontal: SLIDE_MARGIN, + }, + chatSlide: { + width: screenWidth, // Full screen width for proper paging + flex: 1, + paddingHorizontal: SLIDE_MARGIN, // Use padding instead of margin + alignItems: 'center', // Center the content + justifyContent: 'center', + }, + chatContent: { + width: CHAT_WIDTH, // The actual chat content width + flex: 1, + backgroundColor: '#ffffff', + borderRadius: 12, + marginVertical: 8, + shadowColor: '#000', + shadowOffset: {width: 0, height: 4}, + shadowOpacity: 0.1, + shadowRadius: 8, + elevation: 4, + overflow: 'hidden', + }, + chatHeader: { + position: 'relative', + backgroundColor: '#ffffff', + paddingHorizontal: 15, + paddingVertical: 12, + borderBottomWidth: 1, + borderBottomColor: 'rgba(0,0,0,0.1)', + minHeight: 60, + justifyContent: 'center', + alignItems: 'center', + }, + chatHeaderContent: { + alignItems: 'center', + justifyContent: 'center', + width: '100%', + }, + chatTitle: { + fontSize: 18, + fontWeight: 'bold', + color: '#1a1a1a', + marginBottom: 2, + }, + chatSubtitle: { + fontSize: 12, + color: '#666', + fontWeight: '500', + }, + chatContainer: { + flex: 1, + overflow: 'hidden', + }, + sandbox: { + flex: 1, + overflow: 'hidden', + }, + deleteButton: { + position: 'absolute', + left: 15, + top: 15, + padding: 5, + borderRadius: 10, + backgroundColor: '#f44336', + width: 30, + height: 30, + justifyContent: 'center', + alignItems: 'center', + zIndex: 1, + }, + deleteButtonText: { + color: '#ffffff', + fontSize: 20, + fontWeight: 'bold', + margin: -10, + }, + deleteButtonDisabled: { + opacity: 0.5, + }, + addChatCard: { + width: '45%', // Make it 45% of the slide width + height: '60%', // Make it 60% of the slide height + backgroundColor: '#f8f9fa', + borderRadius: 12, + padding: 20, // Reduced padding + alignItems: 'center', + justifyContent: 'center', + shadowColor: '#000', + shadowOffset: {width: 0, height: 2}, + shadowOpacity: 0.1, + shadowRadius: 4, + elevation: 3, + borderWidth: 2, + borderColor: '#dee2e6', + borderStyle: 'dashed', + alignSelf: 'center', // Center horizontally in the slide + }, + addChatContent: { + alignItems: 'center', + }, + addChatIcon: { + fontSize: 30, // Reduced from 40 + color: '#6c757d', + marginBottom: 8, // Reduced margin + }, + addChatIconDisabled: { + opacity: 0.5, + }, + addChatText: { + fontSize: 16, // Reduced from 18 + fontWeight: 'bold', + color: '#6c757d', + marginBottom: 4, // Reduced margin + }, + addChatTextDisabled: { + opacity: 0.5, + }, + addChatLimitText: { + fontSize: 12, + color: '#adb5bd', + }, + + pageIndicators: { + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'center', + paddingVertical: 15, + gap: 8, + }, + pageIndicator: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: '#ccc', + }, + activePageIndicator: { + backgroundColor: '#2196f3', + width: 12, + height: 8, + }, + info: { + backgroundColor: 'rgba(255,255,255,0.9)', + margin: 10, + padding: 12, + borderRadius: 8, + shadowColor: '#000', + shadowOffset: {width: 0, height: 1}, + shadowOpacity: 0.05, + shadowRadius: 2, + elevation: 1, + }, + infoText: { + fontSize: 12, + color: '#666', + textAlign: 'center', + lineHeight: 18, + }, +}) diff --git a/apps/p2p-chat/src/styles/common.ts b/apps/p2p-chat/src/styles/common.ts new file mode 100644 index 0000000..cd97385 --- /dev/null +++ b/apps/p2p-chat/src/styles/common.ts @@ -0,0 +1,108 @@ +import {StyleSheet} from 'react-native' + +// Color Palette +export const colors = { + primary: '#2196f3', + success: '#4caf50', + error: '#f44336', + warning: '#ff9800', + background: '#f8f9fa', + surface: '#ffffff', + text: { + primary: '#1a1a1a', + secondary: '#666', + light: '#999', + white: '#fff', + }, + border: 'rgba(0,0,0,0.1)', + shadow: '#000', +} + +// Spacing +export const spacing = { + xs: 4, + sm: 8, + md: 12, + lg: 16, + xl: 20, +} + +// Typography +export const typography = { + sizes: { + xs: 9, + sm: 10, + md: 12, + lg: 14, + xl: 16, + xxl: 18, + }, + weights: { + normal: '400' as const, + medium: '500' as const, + semibold: '600' as const, + bold: 'bold' as const, + }, +} + +// Common Styles +export const commonStyles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: colors.surface, + }, + row: { + flexDirection: 'row', + alignItems: 'center', + }, + centered: { + justifyContent: 'center', + alignItems: 'center', + }, + shadow: { + shadowColor: colors.shadow, + shadowOffset: {width: 0, height: 2}, + shadowOpacity: 0.1, + shadowRadius: 4, + elevation: 3, + }, + border: { + borderWidth: 1, + borderColor: colors.border, + }, + rounded: { + borderRadius: 8, + }, + roundedLarge: { + borderRadius: 12, + }, +}) + +// Button Styles +export const buttonStyles = StyleSheet.create({ + base: { + paddingHorizontal: spacing.md, + paddingVertical: spacing.sm, + borderRadius: 8, + justifyContent: 'center', + alignItems: 'center', + }, + primary: { + backgroundColor: colors.primary, + }, + success: { + backgroundColor: colors.success, + }, + error: { + backgroundColor: colors.error, + }, + text: { + color: colors.text.white, + fontSize: typography.sizes.lg, + fontWeight: typography.weights.semibold, + }, + disabled: { + backgroundColor: '#ccc', + opacity: 0.5, + }, +}) diff --git a/apps/p2p-chat/src/styles/index.ts b/apps/p2p-chat/src/styles/index.ts new file mode 100644 index 0000000..4338270 --- /dev/null +++ b/apps/p2p-chat/src/styles/index.ts @@ -0,0 +1,2 @@ +export {carouselStyles} from './carousel' +export {buttonStyles, colors, commonStyles, spacing, typography} from './common' diff --git a/apps/p2p-chat/src/types/chat.ts b/apps/p2p-chat/src/types/chat.ts new file mode 100644 index 0000000..5e817ae --- /dev/null +++ b/apps/p2p-chat/src/types/chat.ts @@ -0,0 +1,43 @@ +export interface Message { + id: string + text: string + sender: string + timestamp: number + type: 'sent' | 'received' | 'error' + isError?: boolean + errorReason?: string +} + +export interface ChatAppProps { + userId: string + userName: string + targetOptions: string[] // Array of friend IDs who can receive messages + potentialFriends: {id: string; name: string}[] // Users who can be added as friends + pendingRequests: {id: string; from: string; to: string; timestamp: number}[] // Incoming friend requests + backgroundColor: string + friendshipTrigger?: number // Trigger prop to force re-renders +} + +export interface MessageData { + type: string + messageId?: string + text?: string + senderId?: string + senderName?: string + timestamp: number + target?: string + from?: string + fromName?: string + requestId?: string + action?: string + friend?: string + friendName?: string + reason?: string + errorText?: string + message?: string +} + +export interface GlobalCommunication { + setOnMessage: (callback: (data: any) => void) => void + postMessage: (message: any, targetOrigin?: string) => void +} diff --git a/apps/p2p-chat/src/types/friends.ts b/apps/p2p-chat/src/types/friends.ts new file mode 100644 index 0000000..9dbd71b --- /dev/null +++ b/apps/p2p-chat/src/types/friends.ts @@ -0,0 +1,20 @@ +export interface FriendRequest { + id: string + from: string + to: string + timestamp: number + status?: 'pending' | 'accepted' | 'rejected' +} + +export interface PotentialFriend { + id: string + name: string +} + +export type FriendAction = 'accept' | 'reject' + +export interface FriendNotification { + id: string + text: string + timestamp: number +} diff --git a/apps/p2p-chat/src/types/index.ts b/apps/p2p-chat/src/types/index.ts new file mode 100644 index 0000000..0f8be6a --- /dev/null +++ b/apps/p2p-chat/src/types/index.ts @@ -0,0 +1,12 @@ +export type { + ChatAppProps, + GlobalCommunication, + Message, + MessageData, +} from './chat' +export type { + FriendAction, + FriendNotification, + FriendRequest, + PotentialFriend, +} from './friends' diff --git a/apps/p2p-chat/src/utils/chatHelpers.ts b/apps/p2p-chat/src/utils/chatHelpers.ts new file mode 100644 index 0000000..07d4e13 --- /dev/null +++ b/apps/p2p-chat/src/utils/chatHelpers.ts @@ -0,0 +1,45 @@ +import {ChatMeta} from '../constants' +import {FriendshipManager} from '../services' + +export const getChatHelpers = ( + chatInstances: ChatMeta[], + friendshipManager: FriendshipManager +) => { + const getTargetOptions = (chatId: string): string[] => { + return friendshipManager.getFriends(chatId) + } + + const getPotentialFriends = (chatId: string) => { + return chatInstances + .filter(chat => chat.id !== chatId) // Exclude self + .filter(chat => !friendshipManager.areFriends(chatId, chat.id)) // Exclude existing friends + .filter( + chat => !friendshipManager.hasPendingRequestBetween(chatId, chat.id) + ) // Exclude pending requests + .map(chat => ({id: chat.id, name: chat.userName})) + } + + const getPendingRequests = (chatId: string) => { + return friendshipManager.getPendingRequestsFor(chatId) + } + + const getFriends = (chatId: string) => { + return chatInstances + .filter(chat => chat.id !== chatId) // Exclude self + .filter(chat => friendshipManager.areFriends(chatId, chat.id)) // Only include friends + .map(chat => ({id: chat.id, name: chat.userName})) + } + + return { + getTargetOptions, + getPotentialFriends, + getPendingRequests, + getFriends, + } +} + +export const createChatInstance = (name: string, color: string): ChatMeta => ({ + id: name.toLowerCase(), + userName: name, + backgroundColor: color, +}) diff --git a/apps/p2p-chat/src/utils/colorUtils.ts b/apps/p2p-chat/src/utils/colorUtils.ts new file mode 100644 index 0000000..2c5fbda --- /dev/null +++ b/apps/p2p-chat/src/utils/colorUtils.ts @@ -0,0 +1,36 @@ +// Color interpolation utility functions + +export const hexToRgb = (hex: string) => { + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) + return result + ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16), + } + : {r: 0, g: 0, b: 0} +} + +export const rgbToHex = (r: number, g: number, b: number) => { + return ( + '#' + + ((1 << 24) + (Math.round(r) << 16) + (Math.round(g) << 8) + Math.round(b)) + .toString(16) + .slice(1) + ) +} + +export const interpolateColor = ( + color1: string, + color2: string, + factor: number +) => { + const c1 = hexToRgb(color1) + const c2 = hexToRgb(color2) + + const r = c1.r + factor * (c2.r - c1.r) + const g = c1.g + factor * (c2.g - c1.g) + const b = c1.b + factor * (c2.b - c1.b) + + return rgbToHex(r, g, b) +} diff --git a/apps/p2p-chat/src/utils/index.ts b/apps/p2p-chat/src/utils/index.ts new file mode 100644 index 0000000..a9fbd81 --- /dev/null +++ b/apps/p2p-chat/src/utils/index.ts @@ -0,0 +1,4 @@ +// Export all utility functions +export * from './chatHelpers' +export * from './colorUtils' +export * from './scrollUtils' diff --git a/apps/p2p-chat/src/utils/scrollUtils.ts b/apps/p2p-chat/src/utils/scrollUtils.ts new file mode 100644 index 0000000..bb9bd0d --- /dev/null +++ b/apps/p2p-chat/src/utils/scrollUtils.ts @@ -0,0 +1,78 @@ +import {ChatMeta} from '../constants' +import {interpolateColor} from './colorUtils' + +export const calculateSlideIndex = ( + scrollX: number, + slideWidth: number +): number => { + return Math.round(scrollX / slideWidth) +} + +export const calculateInterpolationProgress = ( + scrollX: number, + slideWidth: number +): { + currentSlideIndex: number + factor: number +} => { + const progress = scrollX / slideWidth + const currentSlideIndex = Math.floor(progress) + const factor = progress - currentSlideIndex + + return {currentSlideIndex, factor} +} + +export const getSlideColors = ( + currentSlideIndex: number, + chatInstances: ChatMeta[] +): {currentSlideColor: string; nextSlideColor: string} => { + const addChatColor = '#f8f9fa' // Light gray for add chat slide + + let currentSlideColor = '#667eea' + let nextSlideColor = '#667eea' + + if (currentSlideIndex < chatInstances.length) { + // Normal chat instance + currentSlideColor = + chatInstances[currentSlideIndex]?.backgroundColor || '#667eea' + + if (currentSlideIndex + 1 < chatInstances.length) { + // Next slide is another chat instance + nextSlideColor = + chatInstances[currentSlideIndex + 1]?.backgroundColor || + currentSlideColor + } else { + // Next slide is the add chat slide + nextSlideColor = addChatColor + } + } else { + // Currently on add chat slide + currentSlideColor = addChatColor + nextSlideColor = addChatColor + } + + return {currentSlideColor, nextSlideColor} +} + +export const calculateBackgroundColor = ( + scrollX: number, + slideWidth: number, + chatInstances: ChatMeta[] +): string => { + const {currentSlideIndex, factor} = calculateInterpolationProgress( + scrollX, + slideWidth + ) + const {currentSlideColor, nextSlideColor} = getSlideColors( + currentSlideIndex, + chatInstances + ) + + const totalSlides = chatInstances.length + 1 // +1 for add chat slide + + if (currentSlideIndex < totalSlides - 1 && factor > 0) { + return interpolateColor(currentSlideColor, nextSlideColor, factor) + } else { + return currentSlideColor + } +} diff --git a/apps/p2p-chat/tsconfig.json b/apps/p2p-chat/tsconfig.json new file mode 100644 index 0000000..88fa317 --- /dev/null +++ b/apps/p2p-chat/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "@react-native/typescript-config" +} diff --git a/apps/p2p-counter/App.tsx b/apps/p2p-counter/App.tsx new file mode 100644 index 0000000..ed973ec --- /dev/null +++ b/apps/p2p-counter/App.tsx @@ -0,0 +1,138 @@ +import SandboxReactNativeView, { + SandboxReactNativeViewRef, +} from '@callstack/react-native-sandbox' +import React, {useRef, useState} from 'react' +import {SafeAreaView, StyleSheet, Switch, Text, View} from 'react-native' +import Toast from 'react-native-toast-message' + +interface CounterSandboxProps { + sourceName: string + backgroundColor: string + targetOrigin: string + isCommunicationEnabled: boolean + onCommunicationToggle: (enabled: boolean) => void + communicationLabel: string +} + +function CounterSandboxView({ + sourceName, + backgroundColor, + targetOrigin, + isCommunicationEnabled, + onCommunicationToggle, + communicationLabel, +}: CounterSandboxProps) { + const sandboxRef = useRef(null) + + const handleMessage = (msg: any) => { + console.log(`Got message from ${sourceName}`, msg) + + Toast.show({ + type: 'info', + text1: sourceName, + text2: JSON.stringify(msg), + }) + } + + const handleError = (error: any) => { + const isFatal = error.isFatal + const message = `Got ${isFatal ? 'fatal' : 'non-fatal'} error from ${sourceName}` + console.warn(message, error) + Toast.show({ + type: 'error', + text1: message, + text2: `${error.name}: ${error.message}`, + }) + return false + } + + return ( + + + {communicationLabel} + + + + + ) +} + +export default function App() { + const [allowAtoB, setAllowAtoB] = useState(false) + const [allowBtoA, setAllowBtoA] = useState(false) + + return ( + + + Sandbox 2 sandbox direct communication + + + + + + + + + + ) +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + header: { + padding: 20, + alignItems: 'center', + }, + sandboxContainer: { + flex: 1, + flexDirection: 'row', + }, + control: { + alignItems: 'center', + margin: 5, + }, + communicationControl: { + flexDirection: 'row', + justifyContent: 'space-between', + alignItems: 'center', + padding: 10, + margin: 5, + }, + sandboxView: { + flex: 1, + padding: 20, + }, +}) diff --git a/apps/p2p-counter/CounterApp.tsx b/apps/p2p-counter/CounterApp.tsx new file mode 100644 index 0000000..4550945 --- /dev/null +++ b/apps/p2p-counter/CounterApp.tsx @@ -0,0 +1,109 @@ +import React, {useCallback, useEffect, useState} from 'react' +import {Button, StyleSheet, Text, View} from 'react-native' + +type AppProps = { + sourceName: string + backgroundColor: string + targetOrigin: string +} + +function App({sourceName, backgroundColor, targetOrigin}: AppProps) { + const [counterThis, setCounterThis] = useState(0) + + const incrementThis = () => { + setCounterThis(prev => prev + 1) + // No message sent to host or targetOrigin + } + + const incrementThat = () => { + // Send message directly to targetOrigin + if (typeof globalThis.postMessage === 'function') { + globalThis.postMessage( + { + type: 'counter_update', + value: 1, // Increment by 1 + source: sourceName, + counter: 'that', + }, + targetOrigin + ) + } + } + + const onMessage = useCallback((payload: any) => { + if (payload.type === 'counter_update') { + setCounterThis(prev => prev + 1) + } + }, []) + + // Set up message handler + useEffect(() => { + if (typeof globalThis.setOnMessage === 'function') { + globalThis.setOnMessage(onMessage) + } + }, [onMessage]) + + return ( + + Sandbox {sourceName} + + + + {counterThis} +