diff --git a/.changeset/calm-poets-film.md b/.changeset/calm-poets-film.md new file mode 100644 index 00000000..ff8fb220 --- /dev/null +++ b/.changeset/calm-poets-film.md @@ -0,0 +1,6 @@ +--- +'brownfield': patch +'@callstack/react-native-brownfield': patch +--- + +feat: support Expo SDK 56 in the Brownfield package and example apps diff --git a/.github/actions/androidapp-road-test/action.yml b/.github/actions/androidapp-road-test/action.yml index 47e1a846..463a5723 100644 --- a/.github/actions/androidapp-road-test/action.yml +++ b/.github/actions/androidapp-road-test/action.yml @@ -74,12 +74,21 @@ runs: yarn run brownfield:publish:android shell: bash - - name: Verify debug AAR exists in Maven Local - run: stat ~/.m2/repository/${{ inputs.rn-project-maven-path }}/0.0.1-SNAPSHOT/brownfieldlib-0.0.1-SNAPSHOT-debug.aar - shell: bash - - - name: Verify release AAR exists in Maven Local - run: stat ~/.m2/repository/${{ inputs.rn-project-maven-path }}/0.0.1-SNAPSHOT/brownfieldlib-0.0.1-SNAPSHOT-release.aar + - name: Verify published AAR exists in Maven Local + run: | + artifact_dir=~/.m2/repository/${{ inputs.rn-project-maven-path }}/0.0.1-SNAPSHOT + release_artifact="$artifact_dir/brownfieldlib-0.0.1-SNAPSHOT-release.aar" + default_artifact="$artifact_dir/brownfieldlib-0.0.1-SNAPSHOT.aar" + + if [ -f "$release_artifact" ]; then + stat "$release_artifact" + elif [ -f "$default_artifact" ]; then + stat "$default_artifact" + else + echo "Expected published AAR was not found in $artifact_dir" + ls -la "$artifact_dir" + exit 1 + fi shell: bash # == AndroidApp == diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a64f3e5b..033fd8da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,8 +22,8 @@ jobs: outputs: packages: ${{ steps.filter.outputs.packages }} rnapp: ${{ steps.filter.outputs.rnapp }} - expo54: ${{ steps.filter.outputs.expo54 }} expo55: ${{ steps.filter.outputs.expo55 }} + expo56: ${{ steps.filter.outputs.expo56 }} androidapp: ${{ steps.filter.outputs.androidapp }} appleapp: ${{ steps.filter.outputs.appleapp }} ci: ${{ steps.filter.outputs.ci }} @@ -41,12 +41,12 @@ jobs: rnapp: - 'apps/RNApp/**' - 'apps/brownfield-example-shared-tests/**' - expo54: - - 'apps/ExpoApp54/**' - - 'apps/brownfield-example-shared-tests/**' expo55: - 'apps/ExpoApp55/**' - 'apps/brownfield-example-shared-tests/**' + expo56: + - 'apps/ExpoApp56/**' + - 'apps/brownfield-example-shared-tests/**' androidapp: - 'apps/AndroidApp/**' appleapp: @@ -127,8 +127,8 @@ jobs: if: | always() && ( - needs.filter.outputs.expo54 == 'true' || needs.filter.outputs.expo55 == 'true' || + needs.filter.outputs.expo56 == 'true' || needs.filter.outputs.androidapp == 'true' || needs.filter.outputs.packages == 'true' || needs.filter.outputs.ci == 'true' @@ -137,8 +137,8 @@ jobs: strategy: matrix: include: - - version: '54' - version: '55' + - version: '56' steps: - name: Checkout @@ -211,8 +211,8 @@ jobs: if: | always() && ( - needs.filter.outputs.expo54 == 'true' || needs.filter.outputs.expo55 == 'true' || + needs.filter.outputs.expo56 == 'true' || needs.filter.outputs.appleapp == 'true' || needs.filter.outputs.packages == 'true' || needs.filter.outputs.ci == 'true' @@ -221,10 +221,10 @@ jobs: strategy: matrix: include: - - version: '54' - run-e2e: 'false' - version: '55' run-e2e: 'true' + - version: '56' + run-e2e: 'true' steps: - name: Checkout @@ -237,4 +237,3 @@ jobs: rn-project-path: apps/ExpoApp${{ matrix.version }} run-e2e: ${{ matrix.run-e2e }} e2e-artifact-name: detox-appleapp-expo${{ matrix.version }} - diff --git a/.yarn/patches/expo-modules-core-npm-55.0.25-brownfield.patch b/.yarn/patches/expo-modules-core-npm-55.0.25-brownfield.patch new file mode 100644 index 00000000..33889ca6 --- /dev/null +++ b/.yarn/patches/expo-modules-core-npm-55.0.25-brownfield.patch @@ -0,0 +1,56 @@ +diff --git a/android/cmake/main.cmake b/android/cmake/main.cmake +index 2fa3ea0c3d7d9771729ad55de63185fdb90a3520..ff72a20c4fcb36e737e2fb2840cbf6a51a2e15d2 100644 +--- a/android/cmake/main.cmake ++++ b/android/cmake/main.cmake +@@ -71,22 +71,31 @@ if (REACT_NATIVE_WORKLETS_DIR) + if (REACT_NATIVE_WORKLETS_DIR) +- add_library(worklets SHARED IMPORTED) +- +- if (${CMAKE_BUILD_TYPE} MATCHES "Debug") +- set(BUILD_TYPE "debug") +- else () +- set(BUILD_TYPE "release") +- endif () +- +- set_target_properties( +- worklets +- PROPERTIES +- IMPORTED_LOCATION +- "${REACT_NATIVE_WORKLETS_DIR}/android/build/intermediates/cmake/${BUILD_TYPE}/obj/${ANDROID_ABI}/libworklets.so" +- ) +- +- target_link_libraries( +- expo-modules-core +- PRIVATE +- worklets +- ) ++ find_package(react-native-worklets CONFIG QUIET) ++ if (react-native-worklets_FOUND) ++ target_link_libraries( ++ expo-modules-core ++ PRIVATE ++ react-native-worklets::worklets ++ ) ++ else () ++ add_library(worklets SHARED IMPORTED) ++ ++ if (${CMAKE_BUILD_TYPE} MATCHES "Debug") ++ set(BUILD_TYPE "debug") ++ else () ++ set(BUILD_TYPE "release") ++ endif () ++ ++ set_target_properties( ++ worklets ++ PROPERTIES ++ IMPORTED_LOCATION ++ "${REACT_NATIVE_WORKLETS_DIR}/android/build/intermediates/cmake/${BUILD_TYPE}/obj/${ANDROID_ABI}/libworklets.so" ++ ) ++ ++ target_link_libraries( ++ expo-modules-core ++ PRIVATE ++ worklets ++ ) ++ endif () + endif () diff --git a/.yarn/patches/expo-updates-npm-56.0.17-0d9c6d9af6.patch b/.yarn/patches/expo-updates-npm-56.0.17-0d9c6d9af6.patch new file mode 100644 index 00000000..5c69f3b9 --- /dev/null +++ b/.yarn/patches/expo-updates-npm-56.0.17-0d9c6d9af6.patch @@ -0,0 +1,13 @@ +diff --git a/ios/EXUpdates.podspec b/ios/EXUpdates.podspec +index c3d463384cc660c413e6f29ae9990fa1421661d8..f347621cc9f51ca4efd4f8d696918c82767e6e14 100644 +--- a/ios/EXUpdates.podspec ++++ b/ios/EXUpdates.podspec +@@ -15,7 +15,7 @@ begin + # No dev client if we are using native debug + if ENV['EX_UPDATES_NATIVE_DEBUG'] != '1' + project_root = ENV['PROJECT_ROOT'] || Pod::Config.instance.installation_root.to_s +- use_dev_client = File.dirname(`node --print "require.resolve('expo-dev-client/package.json', { paths: ['#{__dir__}', '#{project_root}'] })"`).length > 0 ++ use_dev_client = File.dirname(`node --print "try { require.resolve('expo-dev-client/package.json', { paths: ['#{__dir__}', '#{project_root}'] }) } catch { '' }"`).length > 0 + end + rescue + use_dev_client = false diff --git a/.yarn/patches/react-native-reanimated-npm-4.2.1-brownfield.patch b/.yarn/patches/react-native-reanimated-npm-4.2.1-brownfield.patch new file mode 100644 index 00000000..9ef9cf05 --- /dev/null +++ b/.yarn/patches/react-native-reanimated-npm-4.2.1-brownfield.patch @@ -0,0 +1,31 @@ +diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt +index 0c2c3c92ba1d53c14a342ebcd21342ba8141a853..c2ee77d25009a220225f8f2345925f4cc99c72db 100644 +--- a/android/CMakeLists.txt ++++ b/android/CMakeLists.txt +@@ -46,2 +46,3 @@ find_package(fbjni REQUIRED CONFIG) + find_package(ReactAndroid REQUIRED CONFIG) ++find_package(react-native-worklets REQUIRED CONFIG) + +@@ -77,14 +78,0 @@ set_target_properties(reanimated PROPERTIES LINKER_LANGUAGE CXX) +-if(${CMAKE_BUILD_TYPE} MATCHES "Debug") +- set(BUILD_TYPE "debug") +-else() +- set(BUILD_TYPE "release") +-endif() +- +-add_library(worklets SHARED IMPORTED) +- +-set_target_properties( +- worklets +- PROPERTIES +- IMPORTED_LOCATION +- "${REACT_NATIVE_WORKLETS_DIR}/android/build/intermediates/cmake/${BUILD_TYPE}/obj/${ANDROID_ABI}/libworklets.so" +-) +@@ -107,5 +94,5 @@ target_link_libraries( + ReactAndroid::reactnative + ReactAndroid::jsi + fbjni::fbjni +- android +- worklets) ++ android ++ react-native-worklets::worklets) diff --git a/apps/AndroidApp/app/build.gradle.kts b/apps/AndroidApp/app/build.gradle.kts index d32b6717..8476fe23 100644 --- a/apps/AndroidApp/app/build.gradle.kts +++ b/apps/AndroidApp/app/build.gradle.kts @@ -35,6 +35,9 @@ android { create("expo55") { dimension = "app" } + create("expo56") { + dimension = "app" + } create("expobeta") { dimension = "app" } @@ -75,8 +78,9 @@ dependencies { implementation(libs.androidx.compose.material3) implementation(libs.androidx.appcompat) add("expo55Implementation", libs.brownfieldlib.expo55) - add("expobetaImplementation", libs.brownfieldlib.expobeta) + add("expo56Implementation", libs.brownfieldlib.expo56) add("expo54Implementation", libs.brownfieldlib.expo54) + add("expobetaImplementation", libs.brownfieldlib.expobeta) add("vanillaImplementation", libs.brownfieldlib.vanilla) implementation(libs.androidx.fragment.compose) diff --git a/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/BrownfieldStore.kt b/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/BrownfieldStore.kt new file mode 100644 index 00000000..c9e8fa11 --- /dev/null +++ b/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/BrownfieldStore.kt @@ -0,0 +1,4 @@ +package com.callstack.brownfield.android.example + +typealias BrownfieldStore = com.callstack.rnbrownfield.demo.expoapp56.BrownfieldStore +typealias User = com.callstack.rnbrownfield.demo.expoapp56.User diff --git a/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/ReactNativeConstants.kt b/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/ReactNativeConstants.kt new file mode 100644 index 00000000..dfd59f51 --- /dev/null +++ b/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/ReactNativeConstants.kt @@ -0,0 +1,6 @@ +package com.callstack.brownfield.android.example + +object ReactNativeConstants { + const val MAIN_MODULE_NAME = "main" + const val APP_NAME = "Android (Expo 56)" +} diff --git a/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/ReactNativeHostManager.kt b/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/ReactNativeHostManager.kt new file mode 100644 index 00000000..c317ce58 --- /dev/null +++ b/apps/AndroidApp/app/src/expo56/java/com/callstack/brownfield/android/expo/ReactNativeHostManager.kt @@ -0,0 +1,3 @@ +package com.callstack.brownfield.android.example + +typealias ReactNativeHostManager = com.callstack.rnbrownfield.demo.expoapp56.ReactNativeHostManager diff --git a/apps/AndroidApp/gradle/libs.versions.toml b/apps/AndroidApp/gradle/libs.versions.toml index f52bd562..b72dcfc6 100644 --- a/apps/AndroidApp/gradle/libs.versions.toml +++ b/apps/AndroidApp/gradle/libs.versions.toml @@ -16,6 +16,7 @@ gson = "2.13.2" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +brownfieldlib-expo56 = { module = "com.callstack.rnbrownfield.demo.expoapp56:brownfieldlib", version.ref = "brownfieldlib" } brownfieldlib-expo55 = { module = "com.callstack.rnbrownfield.demo.expoapp55:brownfieldlib", version.ref = "brownfieldlib" } brownfieldlib-expobeta = { module = "com.callstack.rnbrownfield.demo.expobeta:brownfieldlib", version.ref = "brownfieldlib" } brownfieldlib-expo54 = { module = "com.callstack.rnbrownfield.demo.expoapp54:brownfieldlib", version.ref = "brownfieldlib" } @@ -41,4 +42,3 @@ gson = { module = "com.google.code.gson:gson", version.ref = "gson" } [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } - diff --git a/apps/AndroidApp/package.json b/apps/AndroidApp/package.json index 8ee08845..af635291 100644 --- a/apps/AndroidApp/package.json +++ b/apps/AndroidApp/package.json @@ -3,7 +3,8 @@ "version": "0.0.1", "private": true, "scripts": { - "build:example:android-consumer:expo": "./gradlew assembleExpo55Release", + "build:example:android-consumer:expo": "./gradlew assembleExpo56Release", + "build:example:android-consumer:expo56": "./gradlew assembleExpo56Release", "build:example:android-consumer:expo55": "./gradlew assembleExpo55Release", "build:example:android-consumer:expobeta": "./gradlew assembleExpobetaRelease", "build:example:android-consumer:expo54": "./gradlew assembleExpo54Release", diff --git a/apps/AppleApp/.detoxrc.expo56.cjs b/apps/AppleApp/.detoxrc.expo56.cjs new file mode 100644 index 00000000..dc21d80f --- /dev/null +++ b/apps/AppleApp/.detoxrc.expo56.cjs @@ -0,0 +1,17 @@ +const { + createAppleAppIosSimDebugDetoxConfig, +} = require('../brownfield-example-shared-tests/detox-rc-appleapp-ios-sim-debug.cjs'); +const { + getAppleAppDetoxVariant, +} = require('../brownfield-example-shared-tests/detox-appleapp-variants.cjs'); + +const variant = getAppleAppDetoxVariant('expo56'); + +/** @type {import('detox').DetoxConfig} */ +module.exports = createAppleAppIosSimDebugDetoxConfig({ + scheme: variant.scheme, + configuration: variant.configuration, + appBinaryName: variant.appBinaryName, + detoxConfiguration: variant.detoxConfiguration, + jestConfigPath: 'e2e/jest.config.expo56.cjs', +}); diff --git a/apps/AppleApp/Brownfield Apple App.xcodeproj/project.pbxproj b/apps/AppleApp/Brownfield Apple App.xcodeproj/project.pbxproj index a8cc22ca..9152bc73 100644 --- a/apps/AppleApp/Brownfield Apple App.xcodeproj/project.pbxproj +++ b/apps/AppleApp/Brownfield Apple App.xcodeproj/project.pbxproj @@ -45,6 +45,20 @@ 79B8BE932FB7273600B94C6F /* hermesvm.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99C2FB4A61400A5F42B /* hermesvm.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 79B8BE942FB7273600B94C6F /* BrownfieldLib.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D9992FB4A61400A5F42B /* BrownfieldLib.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 79B8BE952FB7273600B94C6F /* React.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99D2FB4A61400A5F42B /* React.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 79B8BEA02FB8000000B94C6F /* Brownie.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99B2FB4A61400A5F42B /* Brownie.xcframework */; }; + 79B8BEA12FB8000000B94C6F /* BrownfieldNavigation.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99A2FB4A61400A5F42B /* BrownfieldNavigation.xcframework */; }; + 79B8BEA22FB8000000B94C6F /* ReactNativeDependencies.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99F2FB4A61400A5F42B /* ReactNativeDependencies.xcframework */; }; + 79B8BEA32FB8000000B94C6F /* hermesvm.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99C2FB4A61400A5F42B /* hermesvm.xcframework */; }; + 79B8BEA42FB8000000B94C6F /* ReactBrownfield.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99E2FB4A61400A5F42B /* ReactBrownfield.xcframework */; }; + 79B8BEA52FB8000000B94C6F /* BrownfieldLib.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D9992FB4A61400A5F42B /* BrownfieldLib.xcframework */; }; + 79B8BEA62FB8000000B94C6F /* React.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99D2FB4A61400A5F42B /* React.xcframework */; }; + 79B8BEA72FB8000000B94C6F /* Brownie.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99B2FB4A61400A5F42B /* Brownie.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 79B8BEA82FB8000000B94C6F /* ReactBrownfield.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99E2FB4A61400A5F42B /* ReactBrownfield.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 79B8BEA92FB8000000B94C6F /* ReactNativeDependencies.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99F2FB4A61400A5F42B /* ReactNativeDependencies.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 79B8BEAA2FB8000000B94C6F /* BrownfieldNavigation.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99A2FB4A61400A5F42B /* BrownfieldNavigation.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 79B8BEAB2FB8000000B94C6F /* hermesvm.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99C2FB4A61400A5F42B /* hermesvm.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 79B8BEAC2FB8000000B94C6F /* BrownfieldLib.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D9992FB4A61400A5F42B /* BrownfieldLib.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 79B8BEAD2FB8000000B94C6F /* React.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99D2FB4A61400A5F42B /* React.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 7A1B2C3D4E5F60718293A101 /* Brownie.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99B2FB4A61400A5F42B /* Brownie.xcframework */; }; 7A1B2C3D4E5F60718293A102 /* BrownfieldNavigation.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99A2FB4A61400A5F42B /* BrownfieldNavigation.xcframework */; }; 7A1B2C3D4E5F60718293A103 /* ReactNativeDependencies.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79B1D99F2FB4A61400A5F42B /* ReactNativeDependencies.xcframework */; }; @@ -111,6 +125,23 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + 79B8BEAE2FB8000000B94C6F /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 79B8BEA72FB8000000B94C6F /* Brownie.xcframework in Embed Frameworks */, + 79B8BEA82FB8000000B94C6F /* ReactBrownfield.xcframework in Embed Frameworks */, + 79B8BEA92FB8000000B94C6F /* ReactNativeDependencies.xcframework in Embed Frameworks */, + 79B8BEAA2FB8000000B94C6F /* BrownfieldNavigation.xcframework in Embed Frameworks */, + 79B8BEAB2FB8000000B94C6F /* hermesvm.xcframework in Embed Frameworks */, + 79B8BEAC2FB8000000B94C6F /* BrownfieldLib.xcframework in Embed Frameworks */, + 79B8BEAD2FB8000000B94C6F /* React.xcframework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; 7A1B2C3D4E5F60718293A201 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -141,12 +172,50 @@ 79B1D99F2FB4A61400A5F42B /* ReactNativeDependencies.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = ReactNativeDependencies.xcframework; path = package/ReactNativeDependencies.xcframework; sourceTree = ""; }; 79B8BE802FB7270E00B94C6F /* Brownfield Apple App (ExpoApp54).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Brownfield Apple App (ExpoApp54).app"; sourceTree = BUILT_PRODUCTS_DIR; }; 79B8BE9B2FB7273600B94C6F /* Brownfield Apple App (ExpoApp55).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Brownfield Apple App (ExpoApp55).app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 79B8BEB22FB8000000B94C6F /* Brownfield Apple App (ExpoApp56).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Brownfield Apple App (ExpoApp56).app"; sourceTree = BUILT_PRODUCTS_DIR; }; 7A1B2C3D4E5F60718293A202 /* Brownfield Apple App (ExpoAppBeta).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Brownfield Apple App (ExpoAppBeta).app"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + 79B8BE822FB7270F00B94C6F /* Exceptions for "Brownfield Apple App" folder in "Brownfield Apple App (ExpoApp54)" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Assets.xcassets, + BrownfieldAppleApp.swift, + components/ContentView.swift, + components/GreetingCard.swift, + components/MaterialCard.swift, + components/MessagesView.swift, + components/ReferralsScreen.swift, + components/SettingsScreen.swift, + components/Toast.swift, + ); + target = 79B8BE682FB7270E00B94C6F /* Brownfield Apple App (ExpoApp54) */; + }; + 7A1B2C3D4E5F60718293A203 /* Exceptions for "Brownfield Apple App" folder in "Brownfield Apple App (ExpoAppBeta)" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Assets.xcassets, + BrownfieldAppleApp.swift, + components/ContentView.swift, + components/GreetingCard.swift, + components/MaterialCard.swift, + components/MessagesView.swift, + components/ReferralsScreen.swift, + components/SettingsScreen.swift, + components/Toast.swift, + ); + target = 7A1B2C3D4E5F60718293A301 /* Brownfield Apple App (ExpoAppBeta) */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + /* Begin PBXFileSystemSynchronizedRootGroup section */ 793C76A92EEBF938008A2A34 /* Brownfield Apple App */ = { isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + 79B8BE822FB7270F00B94C6F /* Exceptions for "Brownfield Apple App" folder in "Brownfield Apple App (ExpoApp54)" target */, + 7A1B2C3D4E5F60718293A203 /* Exceptions for "Brownfield Apple App" folder in "Brownfield Apple App (ExpoAppBeta)" target */, + ); path = "Brownfield Apple App"; sourceTree = ""; }; @@ -193,6 +262,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 79B8BEAF2FB8000000B94C6F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 79B8BEA02FB8000000B94C6F /* Brownie.xcframework in Frameworks */, + 79B8BEA12FB8000000B94C6F /* BrownfieldNavigation.xcframework in Frameworks */, + 79B8BEA22FB8000000B94C6F /* ReactNativeDependencies.xcframework in Frameworks */, + 79B8BEA32FB8000000B94C6F /* hermesvm.xcframework in Frameworks */, + 79B8BEA42FB8000000B94C6F /* ReactBrownfield.xcframework in Frameworks */, + 79B8BEA52FB8000000B94C6F /* BrownfieldLib.xcframework in Frameworks */, + 79B8BEA62FB8000000B94C6F /* React.xcframework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 7A1B2C3D4E5F60718293A204 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -239,8 +322,9 @@ 793C76A72EEBF938008A2A34 /* Brownfield Apple App (RNApp).app */, 79B8BE802FB7270E00B94C6F /* Brownfield Apple App (ExpoApp54).app */, 79B8BE9B2FB7273600B94C6F /* Brownfield Apple App (ExpoApp55).app */, - 7A1B2C3D4E5F60718293A202 /* Brownfield Apple App (ExpoAppBeta).app */, - ); + 79B8BEB22FB8000000B94C6F /* Brownfield Apple App (ExpoApp56).app */, + 7A1B2C3D4E5F60718293A202 /* Brownfield Apple App (ExpoAppBeta).app */, + ); name = Products; sourceTree = ""; }; @@ -255,6 +339,7 @@ 793C76A42EEBF938008A2A34 /* Frameworks */, 793C76A52EEBF938008A2A34 /* Resources */, 79688AB82FB3EA8400D728BD /* Embed Frameworks */, + 80A4C4012FBA000000ABC001 /* Embed Additional Packaged Frameworks */, ); buildRules = ( ); @@ -278,6 +363,7 @@ 79B8BE6A2FB7270E00B94C6F /* Frameworks */, 79B8BE722FB7270E00B94C6F /* Resources */, 79B8BE732FB7270E00B94C6F /* Embed Frameworks */, + 80A4C4022FBA000000ABC001 /* Embed Additional Packaged Frameworks */, ); buildRules = ( ); @@ -301,6 +387,7 @@ 79B8BE852FB7273600B94C6F /* Frameworks */, 79B8BE8D2FB7273600B94C6F /* Resources */, 79B8BE8E2FB7273600B94C6F /* Embed Frameworks */, + 80A4C4032FBA000000ABC001 /* Embed Additional Packaged Frameworks */, ); buildRules = ( ); @@ -316,127 +403,280 @@ productReference = 79B8BE9B2FB7273600B94C6F /* Brownfield Apple App (ExpoApp55).app */; productType = "com.apple.product-type.application"; }; - 7A1B2C3D4E5F60718293A301 /* Brownfield Apple App (ExpoAppBeta) */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7A1B2C3D4E5F60718293A405 /* Build configuration list for PBXNativeTarget "Brownfield Apple App (ExpoAppBeta)" */; - buildPhases = ( - 7A1B2C3D4E5F60718293A302 /* Sources */, - 7A1B2C3D4E5F60718293A204 /* Frameworks */, - 7A1B2C3D4E5F60718293A303 /* Resources */, - 7A1B2C3D4E5F60718293A201 /* Embed Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - fileSystemSynchronizedGroups = ( - 793C76A92EEBF938008A2A34 /* Brownfield Apple App */, - ); - name = "Brownfield Apple App (ExpoAppBeta)"; - packageProductDependencies = ( - ); - productName = "Brownfield Apple App"; - productReference = 7A1B2C3D4E5F60718293A202 /* Brownfield Apple App (ExpoAppBeta).app */; - productType = "com.apple.product-type.application"; - }; + 79B8BEB42FB8000000B94C6F /* Brownfield Apple App (ExpoApp56) */ = { + isa = PBXNativeTarget; + buildConfigurationList = 79B8BEB92FB8000000B94C6F /* Build configuration list for PBXNativeTarget "Brownfield Apple App (ExpoApp56)" */; + buildPhases = ( + 79B8BEB12FB8000000B94C6F /* Sources */, + 79B8BEAF2FB8000000B94C6F /* Frameworks */, + 79B8BEB02FB8000000B94C6F /* Resources */, + 79B8BEAE2FB8000000B94C6F /* Embed Frameworks */, + 80A4C4042FBA000000ABC001 /* Embed Additional Packaged Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 793C76A92EEBF938008A2A34 /* Brownfield Apple App */, + ); + name = "Brownfield Apple App (ExpoApp56)"; + packageProductDependencies = ( + ); + productName = "Brownfield Apple App"; + productReference = 79B8BEB22FB8000000B94C6F /* Brownfield Apple App (ExpoApp56).app */; + productType = "com.apple.product-type.application"; + }; + 7A1B2C3D4E5F60718293A301 /* Brownfield Apple App (ExpoAppBeta) */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7A1B2C3D4E5F60718293A405 /* Build configuration list for PBXNativeTarget "Brownfield Apple App (ExpoAppBeta)" */; + buildPhases = ( + 7A1B2C3D4E5F60718293A302 /* Sources */, + 7A1B2C3D4E5F60718293A204 /* Frameworks */, + 7A1B2C3D4E5F60718293A303 /* Resources */, + 7A1B2C3D4E5F60718293A201 /* Embed Frameworks */, + 80A4C4052FBA000000ABC001 /* Embed Additional Packaged Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + 793C76A92EEBF938008A2A34 /* Brownfield Apple App */, + ); + name = "Brownfield Apple App (ExpoAppBeta)"; + packageProductDependencies = ( + ); + productName = "Brownfield Apple App"; + productReference = 7A1B2C3D4E5F60718293A202 /* Brownfield Apple App (ExpoAppBeta).app */; + productType = "com.apple.product-type.application"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - 793C769F2EEBF938008A2A34 /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 2610; - LastUpgradeCheck = 2620; - TargetAttributes = { - 793C76A62EEBF938008A2A34 = { - CreatedOnToolsVersion = 26.1.1; + 793C769F2EEBF938008A2A34 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 2610; + LastUpgradeCheck = 2620; + TargetAttributes = { + 793C76A62EEBF938008A2A34 = { + CreatedOnToolsVersion = 26.1.1; + }; + 79B8BEB42FB8000000B94C6F = { + CreatedOnToolsVersion = 26.1.1; + }; + 7A1B2C3D4E5F60718293A301 = { + CreatedOnToolsVersion = 26.1.1; + }; }; }; - }; - buildConfigurationList = 793C76A22EEBF938008A2A34 /* Build configuration list for PBXProject "Brownfield Apple App" */; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 793C769E2EEBF938008A2A34; - minimizedProjectReferenceProxies = 1; - preferredProjectObjectVersion = 77; - productRefGroup = 793C76A82EEBF938008A2A34 /* Products */; - projectDirPath = ""; - projectRoot = ""; + buildConfigurationList = 793C76A22EEBF938008A2A34 /* Build configuration list for PBXProject "Brownfield Apple App" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 793C769E2EEBF938008A2A34; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = 793C76A82EEBF938008A2A34 /* Products */; + projectDirPath = ""; + projectRoot = ""; targets = ( 793C76A62EEBF938008A2A34 /* Brownfield Apple App (RNApp) */, 79B8BE682FB7270E00B94C6F /* Brownfield Apple App (ExpoApp54) */, 79B8BE832FB7273600B94C6F /* Brownfield Apple App (ExpoApp55) */, + 79B8BEB42FB8000000B94C6F /* Brownfield Apple App (ExpoApp56) */, 7A1B2C3D4E5F60718293A301 /* Brownfield Apple App (ExpoAppBeta) */, ); - - }; + }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - 793C76A52EEBF938008A2A34 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 79B8BE722FB7270E00B94C6F /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 79B8BE8D2FB7273600B94C6F /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7A1B2C3D4E5F60718293A303 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 793C76A52EEBF938008A2A34 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79B8BE722FB7270E00B94C6F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79B8BE8D2FB7273600B94C6F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79B8BEB02FB8000000B94C6F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7A1B2C3D4E5F60718293A303 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 80A4C4012FBA000000ABC001 /* Embed Additional Packaged Frameworks */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PROJECT_DIR}/package", + "${PROJECT_DIR}/embedExtraPackagedFrameworks.sh", + ); + name = "Embed Additional Packaged Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"${PROJECT_DIR}/embedExtraPackagedFrameworks.sh\""; + }; + 80A4C4022FBA000000ABC001 /* Embed Additional Packaged Frameworks */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PROJECT_DIR}/package", + "${PROJECT_DIR}/embedExtraPackagedFrameworks.sh", + ); + name = "Embed Additional Packaged Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"${PROJECT_DIR}/embedExtraPackagedFrameworks.sh\""; + }; + 80A4C4032FBA000000ABC001 /* Embed Additional Packaged Frameworks */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PROJECT_DIR}/package", + "${PROJECT_DIR}/embedExtraPackagedFrameworks.sh", + ); + name = "Embed Additional Packaged Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"${PROJECT_DIR}/embedExtraPackagedFrameworks.sh\""; + }; + 80A4C4042FBA000000ABC001 /* Embed Additional Packaged Frameworks */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PROJECT_DIR}/package", + "${PROJECT_DIR}/embedExtraPackagedFrameworks.sh", + ); + name = "Embed Additional Packaged Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"${PROJECT_DIR}/embedExtraPackagedFrameworks.sh\""; + }; + 80A4C4052FBA000000ABC001 /* Embed Additional Packaged Frameworks */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PROJECT_DIR}/package", + "${PROJECT_DIR}/embedExtraPackagedFrameworks.sh", + ); + name = "Embed Additional Packaged Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"${PROJECT_DIR}/embedExtraPackagedFrameworks.sh\""; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ - 793C76A32EEBF938008A2A34 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 79B8BE692FB7270E00B94C6F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 79B8BE842FB7273600B94C6F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7A1B2C3D4E5F60718293A302 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; + 793C76A32EEBF938008A2A34 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79B8BE692FB7270E00B94C6F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79B8BE842FB7273600B94C6F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 79B8BEB12FB8000000B94C6F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7A1B2C3D4E5F60718293A302 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ @@ -1028,6 +1268,194 @@ }; name = "Release Vanilla"; }; + 79B8BEB52FB8000000B94C6F /* Debug Expo */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + ENABLE_APP_SANDBOX = YES; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Brownfield-Apple-App-Info.plist"; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UIViewControllerBasedStatusBarAppearance = "$(USE_EXPO_HOST_STATUS_BAR_APPEARANCE)"; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.callstack.brownfield.ios.example.Brownfield-iOS-App"; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + SDKROOT = auto; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) USE_EXPO_HOST"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + USE_EXPO_HOST_STATUS_BAR_APPEARANCE = NO; + XROS_DEPLOYMENT_TARGET = 2.0; + }; + name = "Debug Expo"; + }; + 79B8BEB62FB8000000B94C6F /* Release Expo */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + ENABLE_APP_SANDBOX = YES; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Brownfield-Apple-App-Info.plist"; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UIViewControllerBasedStatusBarAppearance = "$(USE_EXPO_HOST_STATUS_BAR_APPEARANCE)"; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.callstack.brownfield.ios.example.Brownfield-iOS-App"; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + SDKROOT = auto; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) USE_EXPO_HOST"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + USE_EXPO_HOST_STATUS_BAR_APPEARANCE = NO; + XROS_DEPLOYMENT_TARGET = 2.0; + }; + name = "Release Expo"; + }; + 79B8BEB72FB8000000B94C6F /* Debug Vanilla */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + ENABLE_APP_SANDBOX = YES; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Brownfield-Apple-App-Info.plist"; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UIViewControllerBasedStatusBarAppearance = "$(USE_EXPO_HOST_STATUS_BAR_APPEARANCE)"; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.callstack.brownfield.ios.example.Brownfield-iOS-App"; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + SDKROOT = auto; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + USE_EXPO_HOST_STATUS_BAR_APPEARANCE = YES; + XROS_DEPLOYMENT_TARGET = 2.0; + }; + name = "Debug Vanilla"; + }; + 79B8BEB82FB8000000B94C6F /* Release Vanilla */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEAD_CODE_STRIPPING = YES; + ENABLE_APP_SANDBOX = YES; + ENABLE_PREVIEWS = YES; + ENABLE_USER_SELECTED_FILES = readonly; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = "Brownfield-Apple-App-Info.plist"; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphoneos*]" = YES; + "INFOPLIST_KEY_UILaunchScreen_Generation[sdk=iphonesimulator*]" = YES; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphoneos*]" = UIStatusBarStyleDefault; + "INFOPLIST_KEY_UIStatusBarStyle[sdk=iphonesimulator*]" = UIStatusBarStyleDefault; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UIViewControllerBasedStatusBarAppearance = "$(USE_EXPO_HOST_STATUS_BAR_APPEARANCE)"; + IPHONEOS_DEPLOYMENT_TARGET = 16.4; + LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks"; + "LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 14.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.callstack.brownfield.ios.example.Brownfield-iOS-App"; + PRODUCT_NAME = "$(TARGET_NAME)"; + REGISTER_APP_GROUPS = YES; + SDKROOT = auto; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2,7"; + USE_EXPO_HOST_STATUS_BAR_APPEARANCE = YES; + XROS_DEPLOYMENT_TARGET = 2.0; + }; + name = "Release Vanilla"; + }; 7A1B2C3D4E5F60718293A401 /* Debug Vanilla */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1475,6 +1903,17 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = "Release Expo"; }; + 79B8BEB92FB8000000B94C6F /* Build configuration list for PBXNativeTarget "Brownfield Apple App (ExpoApp56)" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 79B8BEB52FB8000000B94C6F /* Debug Expo */, + 79B8BEB62FB8000000B94C6F /* Release Expo */, + 79B8BEB72FB8000000B94C6F /* Debug Vanilla */, + 79B8BEB82FB8000000B94C6F /* Release Vanilla */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = "Release Expo"; + }; 7A1B2C3D4E5F60718293A405 /* Build configuration list for PBXNativeTarget "Brownfield Apple App (ExpoAppBeta)" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/apps/AppleApp/Brownfield Apple App.xcodeproj/xcshareddata/xcschemes/Brownfield Apple App Expo 56.xcscheme b/apps/AppleApp/Brownfield Apple App.xcodeproj/xcshareddata/xcschemes/Brownfield Apple App Expo 56.xcscheme new file mode 100644 index 00000000..0db5f92f --- /dev/null +++ b/apps/AppleApp/Brownfield Apple App.xcodeproj/xcshareddata/xcschemes/Brownfield Apple App Expo 56.xcscheme @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + diff --git a/apps/AppleApp/Brownfield Apple App.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist b/apps/AppleApp/Brownfield Apple App.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist index 87fb27c8..7c4a606b 100644 --- a/apps/AppleApp/Brownfield Apple App.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist +++ b/apps/AppleApp/Brownfield Apple App.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist @@ -14,6 +14,11 @@ orderHint 1 + Brownfield Apple App Expo 56.xcscheme + + orderHint + 0 + Brownfield Apple App Vanilla.xcscheme orderHint @@ -37,6 +42,11 @@ primary + 79B8BEB42FB8000000B94C6F + + primary + + diff --git a/apps/AppleApp/Brownfield Apple App/components/ContentView.swift b/apps/AppleApp/Brownfield Apple App/components/ContentView.swift index 0b2ceb83..5081d756 100644 --- a/apps/AppleApp/Brownfield Apple App/components/ContentView.swift +++ b/apps/AppleApp/Brownfield Apple App/components/ContentView.swift @@ -86,7 +86,3 @@ struct ContentView: View { } } } - -#Preview { - ContentView() -} diff --git a/apps/AppleApp/e2e/jest.config.expo56.cjs b/apps/AppleApp/e2e/jest.config.expo56.cjs new file mode 100644 index 00000000..4823f092 --- /dev/null +++ b/apps/AppleApp/e2e/jest.config.expo56.cjs @@ -0,0 +1,19 @@ +const path = require('node:path'); +const { + createDetoxJestConfig, +} = require('../../brownfield-example-shared-tests/e2e/createDetoxJestConfig.cjs'); +const { + getAppleAppDetoxVariant, +} = require('../../brownfield-example-shared-tests/detox-appleapp-variants.cjs'); + +const variant = getAppleAppDetoxVariant('expo56'); + +module.exports = createDetoxJestConfig({ + e2eDir: __dirname, + testMatch: [ + path.join( + __dirname, + `../../brownfield-example-shared-tests/e2e/${variant.e2eTestFile}` + ), + ], +}); diff --git a/apps/AppleApp/embedExtraPackagedFrameworks.sh b/apps/AppleApp/embedExtraPackagedFrameworks.sh new file mode 100644 index 00000000..67b29e65 --- /dev/null +++ b/apps/AppleApp/embedExtraPackagedFrameworks.sh @@ -0,0 +1,86 @@ +#!/bin/sh + +set -eu + +PACKAGE_DIR="${PROJECT_DIR}/package" +FRAMEWORKS_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +if [ ! -d "${PACKAGE_DIR}" ] || [ ! -d "${FRAMEWORKS_DIR}" ]; then + exit 0 +fi + +select_slice_dir() { + xcframework_path="$1" + want_simulator="$2" + + for candidate in "${xcframework_path}"/*; do + [ -d "${candidate}" ] || continue + + if ! find "${candidate}" -maxdepth 1 -type d -name '*.framework' | grep -q .; then + continue + fi + + case "$(basename "${candidate}")" in + *simulator*) + if [ "${want_simulator}" = "yes" ]; then + printf '%s\n' "${candidate}" + return 0 + fi + ;; + *) + if [ "${want_simulator}" = "no" ]; then + printf '%s\n' "${candidate}" + return 0 + fi + ;; + esac + done + + return 1 +} + +sign_framework_if_needed() { + framework_path="$1" + + if [ "${CODE_SIGNING_ALLOWED:-NO}" != "YES" ]; then + return 0 + fi + + sign_identity="${EXPANDED_CODE_SIGN_IDENTITY:--}" + /usr/bin/codesign --force --sign "${sign_identity}" --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der "${framework_path}" +} + +case "${PLATFORM_NAME:-}" in + *simulator*) + want_simulator="yes" + ;; + *) + want_simulator="no" + ;; +esac + +for xcframework_path in "${PACKAGE_DIR}"/*.xcframework; do + [ -d "${xcframework_path}" ] || continue + + framework_name="$(basename "${xcframework_path}" .xcframework)" + destination_path="${FRAMEWORKS_DIR}/${framework_name}.framework" + + if [ -d "${destination_path}" ]; then + continue + fi + + slice_dir="$(select_slice_dir "${xcframework_path}" "${want_simulator}" || true)" + + if [ -z "${slice_dir}" ]; then + continue + fi + + framework_path="$(find "${slice_dir}" -maxdepth 1 -type d -name '*.framework' | head -n 1)" + + if [ -z "${framework_path}" ]; then + continue + fi + + cp -R "${framework_path}" "${destination_path}" + sign_framework_if_needed "${destination_path}" +done diff --git a/apps/AppleApp/package.json b/apps/AppleApp/package.json index 534b5501..e07bb467 100644 --- a/apps/AppleApp/package.json +++ b/apps/AppleApp/package.json @@ -4,18 +4,22 @@ "private": true, "type": "module", "scripts": { - "build:example:ios-consumer:expo": "yarn build:example:ios-consumer:expo55", + "build:example:ios-consumer:expo": "yarn build:example:ios-consumer:expo56", + "build:example:ios-consumer:expo56": "node prepareXCFrameworks.js --appName ExpoApp56 && yarn internal::build::common -scheme \"Brownfield Apple App Expo 56\" -configuration Release", "build:example:ios-consumer:expo54": "node prepareXCFrameworks.js --appName ExpoApp54 && yarn internal::build::common -scheme \"Brownfield Apple App Expo 54\" -configuration Release", "build:example:ios-consumer:expo55": "node prepareXCFrameworks.js --appName ExpoApp55 && yarn internal::build::common -scheme \"Brownfield Apple App Expo 55\" -configuration Release", "build:example:ios-consumer:expobeta": "node prepareXCFrameworks.js --appName ExpoAppBeta && yarn internal::build::common -scheme \"Brownfield Apple App Expo Beta\" -configuration Release", "build:example:ios-consumer:vanilla": "node prepareXCFrameworks.js --appName RNApp && yarn internal::build::common -scheme \"Brownfield Apple App Vanilla\" -configuration \"Release Vanilla\"", - "internal::build::common": "xcodebuild -project \"Brownfield Apple App.xcodeproj\" -sdk iphonesimulator build CODE_SIGNING_ALLOWED=NO -derivedDataPath ./build", + "internal::build::common": "xcodebuild -project \"Brownfield Apple App.xcodeproj\" -sdk iphonesimulator build -derivedDataPath ./build", "e2e:build:ios": "detox build --configuration ios.sim.debug", "e2e:test:ios": "detox test --configuration ios.sim.debug", "e2e:build:ios:expo55": "detox build --config-path .detoxrc.expo55.cjs --configuration ios.sim.debug.expo55", "e2e:test:ios:expo55": "detox test --config-path .detoxrc.expo55.cjs --configuration ios.sim.debug.expo55", + "e2e:build:ios:expo56": "detox build --config-path .detoxrc.expo56.cjs --configuration ios.sim.debug.expo56", + "e2e:test:ios:expo56": "detox test --config-path .detoxrc.expo56.cjs --configuration ios.sim.debug.expo56", "ci:local:e2e:ios": "bash ../../scripts/ci-local-appleapp-ios-e2e.sh", - "ci:local:e2e:ios:expo55": "bash ../../scripts/ci-local-appleapp-ios-e2e.sh --variant expo55" + "ci:local:e2e:ios:expo55": "bash ../../scripts/ci-local-appleapp-ios-e2e.sh --variant expo55", + "ci:local:e2e:ios:expo56": "bash ../../scripts/ci-local-appleapp-ios-e2e.sh --variant expo56" }, "devDependencies": { "@callstack/brownfield-example-shared-tests": "workspace:^", diff --git a/apps/AppleApp/prepareXCFrameworks.js b/apps/AppleApp/prepareXCFrameworks.js index c7a0efd1..bb65bc06 100644 --- a/apps/AppleApp/prepareXCFrameworks.js +++ b/apps/AppleApp/prepareXCFrameworks.js @@ -1,6 +1,5 @@ import path from 'node:path'; import fs from 'node:fs'; -import { execFileSync } from 'node:child_process'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; @@ -40,11 +39,6 @@ const sourcePackagePath = path.join( const targetPackagePath = path.join(__dirname, 'package'); -const prebuiltRnCoreArtifacts = [ - 'React.xcframework', - 'ReactNativeDependencies.xcframework', -]; - /** * The Xcode project is configured to link the following frameworks: * - BrownfieldLib (constant) @@ -59,17 +53,6 @@ const prebuiltRnCoreArtifacts = [ * */ -const validNames = [ - 'BrownfieldLib.xcframework', - 'Brownie.xcframework', - 'hermesvm.xcframework', - 'ReactBrownfield.xcframework', - 'BrownfieldNavigation.xcframework', - // below: optional, emitted when RN is packaged with prebuilt iOS pods - 'React.xcframework', - 'ReactNativeDependencies.xcframework', -]; - if (fs.existsSync(targetPackagePath)) { logger.info(`Removing ${targetPackagePath}\n`); fs.rmSync(targetPackagePath, { recursive: true, force: true }); @@ -86,15 +69,17 @@ const preferredArtifactSourcePath = fs.existsSync(spmArtifactsPath) : sourcePackagePath; for (const file of fs.readdirSync(preferredArtifactSourcePath)) { + const sourcePath = path.join(preferredArtifactSourcePath, file); + if ( - !validNames.includes(file) && - !['hermes.xcframework', 'hermesvm.xcframework'].includes(file) + !fs.statSync(sourcePath).isDirectory() || + !file.endsWith('.xcframework') ) { continue; } fs.cpSync( - path.join(preferredArtifactSourcePath, file), + sourcePath, path.join(targetPackagePath, file), { recursive: true, @@ -104,10 +89,19 @@ for (const file of fs.readdirSync(preferredArtifactSourcePath)) { // handle hermesvm.xcframework / hermes.xcframework let hermesArtifactFound = false; -for (const candidateDir of ['hermes.xcframework', 'hermesvm.xcframework']) { - if (fs.existsSync(path.join(targetPackagePath, candidateDir))) { +if (fs.existsSync(path.join(targetPackagePath, 'hermesvm.xcframework'))) { + hermesArtifactFound = true; +} + +if (fs.existsSync(path.join(targetPackagePath, 'hermes.xcframework'))) { + if (hermesArtifactFound) { + fs.rmSync(path.join(targetPackagePath, 'hermes.xcframework'), { + recursive: true, + force: true, + }); + } else { fs.renameSync( - path.join(targetPackagePath, candidateDir), + path.join(targetPackagePath, 'hermes.xcframework'), path.join(targetPackagePath, 'hermesvm.xcframework') ); hermesArtifactFound = true; @@ -118,23 +112,8 @@ if (!hermesArtifactFound) { throw new Error('Hermes artifact not found'); } -for (const artifact of prebuiltRnCoreArtifacts) { - const xcframeworkPath = path.join(targetPackagePath, artifact); - if (!fs.existsSync(xcframeworkPath)) { - continue; - } - - // RN prebuilts ship with a sealed signature that CocoaPods/brownfield packaging - // can invalidate (module.modulemap drift). Re-sign locally so Xcode can embed them. - logger.info(`Re-signing ${artifact} for AppleApp consumer build`); - execFileSync('codesign', ['--force', '--sign', '-', '--deep', xcframeworkPath], { - stdio: 'inherit', - }); - logger.success(`${artifact} re-signed`); -} - for (const file of fs.readdirSync(targetPackagePath)) { - if (!validNames.includes(file)) { + if (!file.endsWith('.xcframework')) { throw new Error(`Invalid file name: ${file}`); } diff --git a/apps/ExpoApp55/app.json b/apps/ExpoApp55/app.json index 67b61868..274f55e1 100644 --- a/apps/ExpoApp55/app.json +++ b/apps/ExpoApp55/app.json @@ -37,10 +37,23 @@ } } ], - ["@callstack/react-native-brownfield", { "debug": true }], + [ + "@callstack/react-native-brownfield", + { + "debug": true + } + ], "expo-image", "expo-font", - "expo-web-browser" + "expo-web-browser", + [ + "expo-build-properties", + { + "ios": { + "buildReactNativeFromSource": true + } + } + ] ], "experiments": { "typedRoutes": true, diff --git a/apps/ExpoApp55/eslint.config.js b/apps/ExpoApp55/eslint.config.js index a852d76e..6b5c1078 100644 --- a/apps/ExpoApp55/eslint.config.js +++ b/apps/ExpoApp55/eslint.config.js @@ -7,6 +7,9 @@ module.exports = defineConfig([ expoConfig, { ignores: ['dist/*'], + rules: { + 'import/no-unresolved': ['error', { ignore: ['^@callstack/.+$'] }], + }, }, // Jest config is executed by Node (CommonJS); teach ESLint Node globals like __dirname. { diff --git a/apps/ExpoApp55/package.json b/apps/ExpoApp55/package.json index 63375638..691a60a6 100644 --- a/apps/ExpoApp55/package.json +++ b/apps/ExpoApp55/package.json @@ -16,7 +16,7 @@ "brownfield:prepare:android:ci": "cd .. && node --experimental-strip-types --no-warnings ./scripts/prepare-android-build-gradle-for-ci.ts ExpoApp55", "brownfield:package:android": "brownfield package:android --module-name brownfieldlib --variant release --verbose", "brownfield:publish:android": "brownfield publish:android --module-name brownfieldlib --verbose", - "brownfield:package:ios": "brownfield package:ios --scheme BrownfieldLib --configuration Release --verbose", + "brownfield:package:ios": "brownfield package:ios --scheme BrownfieldLib --configuration Release --use-prebuilt-rn-core --verbose", "eas:stg": "EXPO_TOKEN=$EAS_TOKEN eas update --channel production --message 'testing 1st stg channel update' --platform ios --environment staging" }, "dependencies": { @@ -29,12 +29,14 @@ "@react-navigation/elements": "^2.9.10", "@react-navigation/native": "^7.1.28", "expo": "~55.0.23", + "expo-build-properties": "~55.0.14", "expo-constants": "~55.0.16", "expo-device": "~55.0.16", "expo-font": "~55.0.7", "expo-glass-effect": "~55.0.11", "expo-image": "~55.0.10", "expo-linking": "~55.0.15", + "expo-modules-core": "patch:expo-modules-core@npm%3A55.0.25#~/.yarn/patches/expo-modules-core-npm-55.0.25-brownfield.patch", "expo-router": "~55.0.14", "expo-splash-screen": "~55.0.20", "expo-status-bar": "~55.0.6", @@ -46,7 +48,7 @@ "react-dom": "19.2.0", "react-native": "0.83.6", "react-native-gesture-handler": "~2.30.0", - "react-native-reanimated": "4.2.1", + "react-native-reanimated": "patch:react-native-reanimated@npm%3A4.2.1#~/.yarn/patches/react-native-reanimated-npm-4.2.1-brownfield.patch", "react-native-safe-area-context": "~5.6.2", "react-native-screens": "~4.23.0", "react-native-web": "~0.21.0", diff --git a/apps/ExpoApp56/.gitignore b/apps/ExpoApp56/.gitignore new file mode 100644 index 00000000..4b00baf3 --- /dev/null +++ b/apps/ExpoApp56/.gitignore @@ -0,0 +1,43 @@ +# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files + +# dependencies +node_modules/ + +# Expo +.expo/ +dist/ +web-build/ +expo-env.d.ts + +# Native +.kotlin/ +*.orig.* +*.jks +*.p8 +*.p12 +*.key +*.mobileprovision + +# Metro +.metro-health-check* + +# debug +npm-debug.* +yarn-debug.* +yarn-error.* + +# macOS +.DS_Store +*.pem + +# local env files +.env*.local + +# typescript +*.tsbuildinfo + +example + +# generated native folders +/ios +/android diff --git a/apps/ExpoApp56/BrownfieldStore.brownie.ts b/apps/ExpoApp56/BrownfieldStore.brownie.ts new file mode 100644 index 00000000..94e22c72 --- /dev/null +++ b/apps/ExpoApp56/BrownfieldStore.brownie.ts @@ -0,0 +1,21 @@ +import type { BrownieStore } from '@callstack/brownie'; + +export interface BrownfieldStore extends BrownieStore { + counter: number; + user: { + name: string; + }; +} + +export interface SettingsStore extends BrownieStore { + theme: 'light' | 'dark'; + notificationsEnabled: boolean; + privacyMode: boolean; +} + +declare module '@callstack/brownie' { + interface BrownieStores { + BrownfieldStore: BrownfieldStore; + SettingsStore: SettingsStore; + } +} diff --git a/apps/ExpoApp56/README.md b/apps/ExpoApp56/README.md new file mode 100644 index 00000000..4d67aec2 --- /dev/null +++ b/apps/ExpoApp56/README.md @@ -0,0 +1,56 @@ +# Welcome to your Expo app 👋 + +This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app). + +## Get started + +1. Install dependencies + + ```bash + npm install + ``` + +2. Start the app + + ```bash + npx expo start + ``` + +In the output, you'll find options to open the app in a + +- [development build](https://docs.expo.dev/develop/development-builds/introduction/) +- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/) +- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/) +- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo + +You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction). + +## Get a fresh project + +When you're ready, run: + +```bash +npm run reset-project +``` + +This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing. + +### Other setup steps + +- To set up ESLint for linting, run `npx expo lint`, or follow our guide on ["Using ESLint and Prettier"](https://docs.expo.dev/guides/using-eslint/) +- If you'd like to set up unit testing, follow our guide on ["Unit Testing with Jest"](https://docs.expo.dev/develop/unit-testing/) +- Learn more about the TypeScript setup in this template in our guide on ["Using TypeScript"](https://docs.expo.dev/guides/typescript/) + +## Learn more + +To learn more about developing your project with Expo, look at the following resources: + +- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides). +- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web. + +## Join the community + +Join our community of developers creating universal apps. + +- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute. +- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions. diff --git a/apps/ExpoApp56/RNApp.tsx b/apps/ExpoApp56/RNApp.tsx new file mode 100644 index 00000000..5e06ccc1 --- /dev/null +++ b/apps/ExpoApp56/RNApp.tsx @@ -0,0 +1,77 @@ +import { SafeAreaView } from 'react-native-safe-area-context'; +import { Button, StyleSheet, Text, View } from 'react-native'; +import BrownfieldNavigation from '@callstack/brownfield-navigation'; +import { checkAndFetchUpdate } from './src/utils/expo-rn-updates'; + +import Counter from './src/components/counter'; + +type RNAppProps = { + nativeOsVersionLabel?: string; +}; + +export default function RNApp({ nativeOsVersionLabel }: RNAppProps) { + return ( + + Expo React Native Brownfield + + {nativeOsVersionLabel ? ( + + {nativeOsVersionLabel} + + ) : null} + + + + +