diff --git a/.circleci/config.yml b/.circleci/config.yml index 36ffd0eed..8d228f68b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -31,6 +31,10 @@ jobs: environment: NODE_OPTIONS: "--max-old-space-size=4096" + - run: + name: Build the Project + command: yarn run build + - run: name: Install AEPSampleApp Dependencies command: cd apps/AEPSampleApp && yarn install --immutable --network-timeout 300000 @@ -38,10 +42,6 @@ jobs: environment: NODE_OPTIONS: "--max-old-space-size=4096" - - run: - name: Build the Project - command: yarn run build - - run: name: Expo Prebuild command: cd apps/AEPSampleAppNewArchEnabled && npx expo prebuild @@ -172,7 +172,7 @@ jobs: command: sudo xcode-select -s /Applications/Xcode.app - node/install: - node-version: '20.19.4' + node-version: '22.12.0' - run: name: Enable Corepack diff --git a/apps/AEPSampleApp/.gitignore b/apps/AEPSampleApp/.gitignore index 0cab2ac6f..7cc8b51e6 100644 --- a/apps/AEPSampleApp/.gitignore +++ b/apps/AEPSampleApp/.gitignore @@ -61,6 +61,8 @@ yarn-error.log # Temporary files created by Metro to check the health of the file watcher .metro-health-check* +.metro-build-matrix.log +.metro-build-matrix.pid # testing /coverage diff --git a/apps/AEPSampleApp/App.tsx b/apps/AEPSampleApp/App.tsx index 1fd42327d..c5e072eee 100644 --- a/apps/AEPSampleApp/App.tsx +++ b/apps/AEPSampleApp/App.tsx @@ -35,7 +35,7 @@ import { useState, useEffect, createContext, useContext } from 'react'; const STORAGE_KEY = 'aep_app_id'; -const DEFAULT_APP_ID = ''; +const DEFAULT_APP_ID = '3149c49c3910/0f12baf27522/launch-0d096c129660-development'; export const AppContext = createContext({ appId: DEFAULT_APP_ID, diff --git a/apps/AEPSampleApp/README.md b/apps/AEPSampleApp/README.md index d50ed994a..6c28e17a1 100644 --- a/apps/AEPSampleApp/README.md +++ b/apps/AEPSampleApp/README.md @@ -4,6 +4,7 @@ - [Introduction](#introduction) - [Prerequisites](#prerequisites) - [Get Started](#how-to-run-the-sample-app) +- [Optimize extension and build matrix](#optimize-extension-and-build-matrix) - [Validate with Assurance](#validate-with-assurance) - [Resources and Troubleshooting](#resources-and-troubleshooting) @@ -78,6 +79,30 @@ npx react-native start Then navigate to apps/AEPSampleApp/android, double click on the `build.gradle` file, and run the app in Android Studio. +### Optimize extension and build matrix + +AEPSampleApp targets **React Native 0.85** with **New Architecture enabled**. It links `@adobe/react-native-aepoptimize` from `packages/optimize` for local development and includes **OptimizeView** (`extensions/OptimizeView.tsx`) with buttons for the Optimize smoke scenarios (update propositions, listeners, display/tap offers, clear cache, and batch display). + +To switch Optimize native wiring without editing Gradle/Podfiles by hand, use the build matrix script. On **Android new arch**, `USE_INTEROP_ROOT` selects bridge vs turbo. On **iOS new arch**, both flag values compile to the same SpecBase turbo binary — `ios-interop` is an optional compile-flag parity check, not a separate RN interop path. + +```bash +cd apps/AEPSampleApp +yarn build:matrix:list # list RN 0.85 cells +yarn build:ios:turbo # iOS new arch + turbo (primary iOS cell) +yarn build:ios:interop # iOS new arch — USE_INTEROP_ROOT compile parity (optional) +yarn build:android:turbo # Android new arch + Turbo Module +yarn build:android:interop # Android new arch + bridge module +yarn build:both:turbo # both platforms, turbo on Android +``` + +Each `yarn build:*` preset runs `scripts/build-matrix.sh` with `--sync --run` (syncs deps, builds, starts Metro, and launches the app). For build-only: + +```bash +./scripts/build-matrix.sh --preset android-turbo -c full --sync --build-only +``` + +**Validated cells (June 2026):** `aep-ios-new-turbo`, `aep-android-new-interop`, and `aep-android-new-turbo` — **8/8** smoke tests pass on each. `aep-ios-new-interop` is compile-flag parity with `aep-ios-new-turbo` (same SpecBase runtime). See [Optimize package README](../../packages/optimize/README.md#validation-matrix-june-2026) for the full cross-app matrix including BareSampleApp on RN 0.76. + ### Validate with Assurance: Assurance is integrated in the sample app for validating the events and flows. diff --git a/apps/AEPSampleApp/android/build.gradle b/apps/AEPSampleApp/android/build.gradle index 3ed3f9bdf..69f69b2a0 100644 --- a/apps/AEPSampleApp/android/build.gradle +++ b/apps/AEPSampleApp/android/build.gradle @@ -15,3 +15,19 @@ plugins { id("org.jetbrains.kotlin.android") version "2.1.20" apply false id("com.facebook.react.rootproject") } + +// USE_INTEROP_ROOT for @adobe/react-native-aepoptimize (RN 0.85 / Gradle 9). +// gradle.properties USE_INTEROP_ROOT is toggled by scripts/build-matrix.sh. +def optimizeUseInteropRoot = findProperty("USE_INTEROP_ROOT") ?: "false" + +gradle.beforeProject { project -> + if (project.name == "adobe_react-native-aepoptimize") { + project.afterEvaluate { + project.android { + defaultConfig { + buildConfigField "boolean", "USE_INTEROP_ROOT", optimizeUseInteropRoot + } + } + } + } +} diff --git a/apps/AEPSampleApp/android/gradle.properties b/apps/AEPSampleApp/android/gradle.properties index b866a0ae2..f0382d997 100644 --- a/apps/AEPSampleApp/android/gradle.properties +++ b/apps/AEPSampleApp/android/gradle.properties @@ -36,6 +36,9 @@ reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 # are providing them. newArchEnabled=true +# USE_INTEROP_ROOT for @adobe/react-native-aepoptimize (build-matrix.sh toggles this). +USE_INTEROP_ROOT=false + # 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/AEPSampleApp/extensions/OptimizeView.tsx b/apps/AEPSampleApp/extensions/OptimizeView.tsx index a37813fd9..e18f83a75 100644 --- a/apps/AEPSampleApp/extensions/OptimizeView.tsx +++ b/apps/AEPSampleApp/extensions/OptimizeView.tsx @@ -10,7 +10,7 @@ OF ANY KIND, either express or implied. See the License for the specific languag governing permissions and limitations under the License. */ -import React, {useState} from 'react'; +import React, {useMemo, useState} from 'react'; import { Optimize, DecisionScope, @@ -27,6 +27,7 @@ import { useWindowDimensions, TextInput, StyleSheet, + ScrollView, } from 'react-native'; import {RecyclerListView, DataProvider, LayoutProvider} from 'recyclerlistview'; @@ -47,6 +48,22 @@ const defaultPropositions = { jsonProposition: '{"Type": "JSON place holder"}', }; +function SmokeButton({ + id, + title, + onPress, +}: { + id: string; + title: string; + onPress: () => void; +}) { + return ( + +