Skip to content

Conversation

@uc-brunosouza
Copy link
Collaborator

@uc-brunosouza uc-brunosouza commented Oct 27, 2025

Summary by CodeRabbit

  • New Features

    • TurboModule-style native integration and generated JNI/codegen stubs for improved native-JS bridge.
  • Updates

    • New Architecture enabled for Android and iOS; sample app updated to new host/bridge patterns.
    • React → 19.1.0 and React Native → 0.81.4; iOS build and Podfile modernized for C++20 and new-arch support.
  • Bug Fixes

    • Packaging, build ordering and autolinking fixes to improve native build reliability.
  • Chores

    • Added/updated developer scripts and packaging/publish utilities.

@coderabbitai
Copy link

coderabbitai bot commented Oct 27, 2025

Walkthrough

Migrates the library to React Native’s New Architecture and TurboModules: adds TurboReactPackage/Kotlin wiring, JNI/C++ stubs and CMake targets, TypeScript TurboModule typings and codegen, updates Android/iOS build configs and sample apps, and introduces scripts for codegen, packaging and iOS build fixes.

Changes

Cohort / File(s) Summary
Android Build & Flags
android/build.gradle.kts, android/gradle.properties, android/build-legacy.gradle
Added top-level gradle flags (usercentricsVersion, reactNativeVersion, isNewArchitectureEnabled, isHermesEnabled, BooleanProperty), switched to kotlin-android, conditional RN plugin application, wired BuildConfig new-arch flag, added generated codegen sourceSets, removed explicit hermesEnabled and added afterEvaluate task dependency fix.
Android Kotlin Module
android/src/main/java/com/usercentrics/reactnative/RNUsercentricsPackage.kt
Converted package to extend TurboReactPackage, added @ReactModuleList, implemented getModule and getReactModuleInfoProvider, returns emptyList() for view managers.
Android JNI & C++
android/src/main/jni/CMakeLists.txt, android/src/main/jni/RNUsercentricsModule.cpp, android/src/main/jni/rn_usercentrics.cpp
Added CMake targets and compile flags (C++20), created placeholder JSI-exported RNUsercentricsModule_ModuleProvider, and added JNI_OnLoad bootstrap file.
Codegen & Build Scripts
scripts/generate-codegen-jni.js, scripts/publish-local.sh, package.json
Added codegen script producing JNI/CMake stubs, updated publish-local npm pack handling, added prepublish/pack-local scripts and codegenConfig and files entries in package.json.
TypeScript TurboModule Types
src/NativeUsercentrics.ts, src/fabric/NativeUsercentricsModule.ts
Switched runtime lookup to TurboModuleRegistry with fallback to NativeModules, Spec interfaces now extend TurboModule, added Fabric TurboModule declaration with strongly-typed methods.
Sample Android (host/app)
sample/android/app/build.gradle.kts, sample/android/app/src/main/.../MainActivity.kt, sample/android/app/src/main/.../MainApplication.kt, sample/android/gradle.properties
Removed legacy packaging tweaks, MainActivity now uses BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, MainApplication refactored to DefaultReactNativeHost + PackageList, sample enabled new architecture flag.
iOS Podfile & Project
sample/ios/Podfile, sample/ios/sample.xcodeproj/..., sample/ios/sample-Bridging-Header.h, sample/ios/sample/AppDelegate.swift, sample/ios/sample/Info.plist
Added dynamic RCT_NEW_ARCH_ENABLED propagation and post_install adjustments (C++ flags, C++20, modular headers, RN 0.81 fixes), added Swift bridging header and Xcode buildsetting updates, refactored AppDelegate bundle URL handling, removed RCTNewArchEnabled from Info.plist.
Sample iOS Utilities & Scripts
sample/scripts/fix-react-logger.sh, sample/scripts/test-ios-build.sh
Added script to fix React-logger umbrella header for Xcode 26 and an end-to-end iOS build/test script.
Sample Metro & Dependencies
sample/metro.config.js, sample/package.json, sample/patches/react-native+0.79.6.patch
Removed metro exclusionList usage, updated sample dependencies (React/RN upgrades), added scripts, and applied RN header typedef patch.
Packaging & Sample Misc
sample/android/app/build.gradle.kts, README.md, scripts/check-requirements.sh
Removed JNI pickFirsts/legacy packaging flags in sample build, updated README requirements (Android API, Gradle, Kotlin notes), and tightened SDK/Kotlin checks script.
Privacy Config
sample/ios/sample/PrivacyInfo.xcprivacy
Reordered three NSPrivacyAccessedAPIType entries and updated corresponding reason codes.

Sequence Diagram(s)

sequenceDiagram
    participant JS as JavaScript/TS
    participant TMReg as TurboModuleRegistry
    participant Native as NativeModules
    participant RNHost as ReactNativeHost
    participant TRP as TurboReactPackage
    participant Kt as KotlinModule
    participant JNI as JNI/C++

    JS->>TMReg: get('RNUsercentricsModule')
    alt TurboModule available
        TMReg-->>JS: TurboModule proxy
    else
        JS->>Native: NativeModules.RNUsercentricsModule
        Native-->>JS: legacy module
    end

    TMReg->>RNHost: resolve package
    RNHost->>TRP: getModule(name)
    TRP->>Kt: instantiate RNUsercentricsModule
    Kt->>JNI: (optional native calls)
    JNI->>JNI: RNUsercentricsModule_ModuleProvider() (placeholder)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • RNUsercentricsPackage.kt: ReactModuleInfoProvider metadata and new-arch conditional behavior.
  • CMakeLists / JNI / C++ files: RN version branching, include paths, linker targets and C++20 flags.
  • scripts/generate-codegen-jni.js: correctness of generated headers, symbols, and output paths.
  • MainApplication/MainActivity refactor: DefaultReactNativeHost wiring and new-arch entrypoint loading.
  • iOS Podfile / Xcodeproj changes: post_install flags, bridging header placement, and buildsetting consistency.

Possibly related PRs

Suggested reviewers

  • uc-brunosilva

Poem

🐰 I hop through code where TurboModules spring,
Kotlin greets JS, and JNI learns to sing,
Codegen seeds scattered, CMake hums along,
New-arch dawns early — builds run strong,
Tiny paws pushed changes — now merge and bring a song 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 8.33% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "feat: fabric support" directly describes the primary objective of this changeset. The modifications across multiple files—including conversion of RNUsercentricsPackage to TurboReactPackage, addition of codegen JNI files, TypeScript TurboModule declarations, and configuration updates for both Android and iOS—are all focused on implementing Fabric support (React Native's new architecture). The title is concise, specific, uses conventional commit format, and clearly communicates the main change without vagueness or unnecessary detail. A developer reviewing the repository history would immediately understand that this PR introduces Fabric support to the SDK.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/fix-ios-sample

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
scripts/publish-local.sh (1)

7-7: Harden packaging: enable pipefail, parse npm JSON, and verify file exists.

Without pipefail, a failing npm pack can look successful and produce a bogus filename. Parse --json instead and assert the tarball exists.

-7 set -e
+7 set -euo pipefail

-92 PACKAGE_FILE=$(npm pack 2>&1 | tail -1)
+92 PACKAGE_FILE="$(npm pack --json | jq -r '.[0].filename')"
+93 # Fallback if --json is unsupported (older npm)
+94 if [ -z "$PACKAGE_FILE" ] || [[ "$PACKAGE_FILE" == "null" ]]; then
+95   PACKAGE_FILE="$(npm pack 2>&1 | rg -n --no-line-number -o '[^[:space:]]+\.tgz$' | tail -1 || true)"
+96 fi
+97 if [ -z "$PACKAGE_FILE" ] || [ ! -f "$PACKAGE_FILE" ]; then
+98   print_error "Failed to create npm package (no .tgz produced)."
+99   exit 1
+100 fi

-101 # Get absolute path of the package (macOS compatible)
-102 PACKAGE_PATH="$(pwd)/$PACKAGE_FILE"
+101 # Get absolute path of the package (macOS compatible)
+102 PACKAGE_PATH="$(pwd)/$PACKAGE_FILE"
+103 # Sanity check
+104 [ -f "$PACKAGE_PATH" ] || { print_error "Package path not found: $PACKAGE_PATH"; exit 1; }

Also applies to: 92-92, 101-103

package.json (3)

95-102: Move tool/runtime-internal packages out of dependencies.

These should not be runtime deps of a library; they bloat consumers and can conflict with RN.

  • Remove hermes-engine from dependencies (RN provides Hermes).
  • Remove npm and install from dependencies; if needed, devDependencies or scripts only.
   "dependencies": {
-    "hermes-engine": "^0.11.0",
-    "install": "^0.13.0",
-    "npm": "^11.6.0",
     "react-native-safe-area-context": "^5.6.1",
     "react-native-screens": "^4.16.0",
     "react-native-webview": "^13.16.0"
   },

12-19: Restore exclusion of android/build to prevent publishing generated build artifacts.

The prepublishOnly script runs node scripts/generate-codegen-jni.js, which creates files under android/build/generated/source/codegen/jni. The current files array includes "android" but lacks the "!android/build" exclusion, so these generated artifacts will be published in the npm tarball.

Apply this diff:

   "files": [
     "android",
     "ios",
     "lib",
     "src",
     "react-native-usercentrics.podspec",
     "react-native.config.js",
+    "!android/build",
     "!.DS_Store",

47-68: Replace react-native-codegen with @react-native/codegen and align version to match React Native 0.79.x.

The package.json currently specifies the legacy react-native-codegen@^0.0.7, but for React Native 0.79.x, use @react-native/codegen, version that matches your RN release (e.g. @react-native/[email protected]).

Update devDependencies:

-    "react-native-codegen": "^0.0.7",
+    "@react-native/codegen": "^0.79.0",
🧹 Nitpick comments (13)
sample/scripts/test-ios-build.sh (3)

36-41: Consider removing or conditionally enabling the -quiet flag to improve build debugging.

The -quiet flag suppresses build output, which makes it harder to diagnose compilation failures. For a test script, verbose output can be valuable for CI/CD logs and developer troubleshooting.

Apply this diff to remove the -quiet flag:

 xcodebuild build \
   -workspace sample.xcworkspace \
   -scheme sample \
   -destination "platform=iOS Simulator,id=$SIMULATOR" \
   -configuration Debug \
-  -quiet
+

Alternatively, make it conditional:

XCODEBUILD_FLAGS="${XCODEBUILD_FLAGS:--quiet}"
xcodebuild build \
  -workspace sample.xcworkspace \
  -scheme sample \
  -destination "platform=iOS Simulator,id=$SIMULATOR" \
  -configuration Debug \
  $XCODEBUILD_FLAGS

1-49: Add set -e at the beginning of the script to fail fast on errors.

Currently, if any command fails (e.g., pod install), the script continues executing, potentially masking the root cause. Adding set -e ensures the script exits immediately on the first error.

Apply this diff to add early error handling:

 #!/bin/bash
+set -e
 
 # Script to test iOS compilation after React-logger fixes

This ensures robust error handling without manually adding || exit 1 to every command.


44-45: Avoid hardcoding version references in the success message, as they become stale.

Lines 44–45 reference "Xcode 26 + React Native 0.79," which may not reflect the actual versions being tested and could confuse future developers.

Consider removing or parameterizing the version reference:

-    echo "✅ Compilation successful! React-logger fixes worked."
-    echo "🎉 Project ready for development with Xcode 26 + React Native 0.79!"
+    echo "✅ Compilation successful! React-logger fixes worked."
+    echo "🎉 Project ready for development!"
sample/android/app/src/main/java/com/usercentrics/reactnativesdk/sample/MainApplication.kt (2)

17-23: Defer host creation to reduce cold-start work.

Make reactNativeHost lazy to avoid instantiating before it’s needed. No behavior change; small startup win.

-    override val reactNativeHost: ReactNativeHost =
-        object : DefaultReactNativeHost(this) {
+    override val reactNativeHost: ReactNativeHost by lazy(LazyThreadSafetyMode.NONE) {
+        object : DefaultReactNativeHost(this) {
             override fun getPackages(): List<ReactPackage> =
                 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
-        }
+        }
+    }

Also applies to: 25-31


33-34: Optional: cache ReactHost.

getDefaultReactHost likely memoizes, but if not, prefer lazy to ensure a single instance.

-    override val reactHost: ReactHost
-        get() = getDefaultReactHost(applicationContext, reactNativeHost)
+    override val reactHost: ReactHost by lazy(LazyThreadSafetyMode.NONE) {
+        getDefaultReactHost(applicationContext, reactNativeHost)
+    }

If the current RN version guarantees memoization, feel free to keep as-is.

sample/ios/sample.xcodeproj/project.pbxproj (2)

374-384: Header search paths: only needed if you keep legacy <React/...> imports.

Given RN’s modular frameworks, prefer guarded, module‑specific imports (React_NativeModulesApple, React_Fabric) in the bridging header and avoid expanding HEADER_SEARCH_PATHS further. If you must keep <React/...>, add a path to the umbrella React headers produced by your Pods setup (e.g., …/React.framework/Headers) to both Debug/Release configs.

Please confirm which of these exists in your Pods:

  • Pods/.../React.framework/Headers
  • Pods/.../React-Core/React.framework/Headers
  • Pods/.../Headers/Public/React

Also applies to: 459-469


267-267: Empty DEVELOPMENT_TEAM blocks device builds.

Optional: set DEVELOPMENT_TEAM for Debug so the sample can run on a device. Simulators are unaffected.

If you want, I can prepare a small xcconfig overlay to inject your team ID locally without committing it.

sample/ios/sample/AppDelegate.swift (1)

12-20: Use the two-arg jsBundleURL(..., fallbackResource: nil) for RN API stability.

Minor: this avoids signature drift across RN versions and is equivalent in behavior.

-    guard let bundleURL = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") else {
+    guard let bundleURL = RCTBundleURLProvider.sharedSettings()
+      .jsBundleURL(forBundleRoot: "index", fallbackResource: nil) else {
       fatalError("Unable to find bundle URL")
     }
sample/ios/Podfile (3)

27-32: Remove trailing comma after last arg in use_react_native!.

Minor Ruby style fix (and matches linter hint).

   use_react_native!(
     :path => config[:reactNativePath],
     :hermes_enabled => true,
-    :fabric_enabled => $RCT_NEW_ARCH_ENABLED,
-    :new_arch_enabled => $RCT_NEW_ARCH_ENABLED,
+    :fabric_enabled => $RCT_NEW_ARCH_ENABLED,
+    :new_arch_enabled => $RCT_NEW_ARCH_ENABLED
   )

63-66: Do not disable all compiler warnings globally.

GCC_WARN_INHIBIT_ALL_WARNINGS = YES hides signal on real issues across all pods. Prefer addressing specific warnings (you already handle quoted includes) or scope to targets that truly need it.

-        config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'] = 'YES'
+        # Leave compiler warnings enabled; handle specific noisy cases instead.
+        # config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'] = 'YES'

67-69: Be cautious forcing C++20 for every Pod.

Some pods pin to C++17 and will fail with C++20. If not strictly required, omit or scope to targets that need it (e.g., React-Core, hermes).

-        config.build_settings['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++20'
-        config.build_settings['CLANG_CXX_LIBRARY'] = 'libc++'
+        # If a specific pod requires C++20, set it on that target only.
+        # config.build_settings['CLANG_CXX_LANGUAGE_STANDARD'] = 'c++20'
+        config.build_settings['CLANG_CXX_LIBRARY'] = 'libc++'
android/src/main/java/com/usercentrics/reactnative/RNUsercentricsPackage.kt (1)

41-41: Confirm hasConstants flag.

Set to true only if the module actually exports constants; otherwise set to false to avoid unnecessary initialization work.

If no constants are exported, flip to false.

android/build.gradle.kts (1)

4-9: Consider extracting BooleanProperty to a shared buildSrc utility.

The BooleanProperty helper is well-written, but if it's used across multiple build scripts (or likely to be), extracting it to buildSrc/src/main/kotlin/... follows Gradle best practices and improves DRY compliance.

However, for a single-file usage, this implementation is acceptable. Verify: is this function also used in ios/Podfile or other build configs?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ebee3e4 and 30554df.

⛔ Files ignored due to path filters (3)
  • package-lock.json is excluded by !**/package-lock.json
  • sample/ios/Podfile.lock is excluded by !**/*.lock
  • sample/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (25)
  • android/build.gradle.kts (4 hunks)
  • android/gradle.properties (1 hunks)
  • android/src/main/java/com/usercentrics/reactnative/RNUsercentricsPackage.kt (1 hunks)
  • android/src/main/jni/CMakeLists.txt (1 hunks)
  • android/src/main/jni/RNUsercentricsModule.cpp (1 hunks)
  • android/src/main/jni/rn_usercentrics.cpp (1 hunks)
  • package.json (3 hunks)
  • react-native.config.js (1 hunks)
  • sample/android/app/build.gradle.kts (0 hunks)
  • sample/android/app/src/main/java/com/usercentrics/reactnativesdk/sample/MainActivity.kt (1 hunks)
  • sample/android/app/src/main/java/com/usercentrics/reactnativesdk/sample/MainApplication.kt (1 hunks)
  • sample/android/gradle.properties (1 hunks)
  • sample/ios/Podfile (2 hunks)
  • sample/ios/sample-Bridging-Header.h (1 hunks)
  • sample/ios/sample.xcodeproj/project.pbxproj (13 hunks)
  • sample/ios/sample/AppDelegate.swift (1 hunks)
  • sample/metro.config.js (0 hunks)
  • sample/package.json (2 hunks)
  • sample/patches/react-native+0.79.6.patch (1 hunks)
  • sample/scripts/fix-react-logger.sh (1 hunks)
  • sample/scripts/test-ios-build.sh (1 hunks)
  • scripts/generate-codegen-jni.js (1 hunks)
  • scripts/publish-local.sh (2 hunks)
  • src/NativeUsercentrics.ts (3 hunks)
  • src/fabric/NativeUsercentricsModule.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • sample/metro.config.js
  • sample/android/app/build.gradle.kts
🧰 Additional context used
🧬 Code graph analysis (3)
src/NativeUsercentrics.ts (1)
src/fabric/NativeUsercentricsModule.ts (1)
  • Spec (4-49)
src/fabric/NativeUsercentricsModule.ts (1)
src/NativeUsercentrics.ts (1)
  • Spec (16-61)
android/src/main/jni/RNUsercentricsModule.cpp (1)
ios/RNUsercentricsModule.swift (1)
  • moduleName (23-25)
🪛 Clang (14.0.6)
android/src/main/jni/rn_usercentrics.cpp

[error] 1-1: 'jni.h' file not found

(clang-diagnostic-error)

android/src/main/jni/RNUsercentricsModule.cpp

[error] 1-1: 'ReactCommon/JavaTurboModule.h' file not found

(clang-diagnostic-error)

sample/ios/sample-Bridging-Header.h

[error] 5-5: 'React/RCTBridgeModule.h' file not found

(clang-diagnostic-error)

🪛 RuboCop (1.81.1)
sample/ios/Podfile

[convention] 31-31: Avoid comma after the last parameter of a method call.

(Style/TrailingCommaInArguments)

🪛 Shellcheck (0.11.0)
sample/scripts/test-ios-build.sh

[warning] 8-8: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.

(SC2164)

🔇 Additional comments (23)
sample/android/app/src/main/java/com/usercentrics/reactnativesdk/sample/MainApplication.kt (3)

4-13: Imports align with modern RN defaults.

Good switch to PackageList, DefaultReactNativeHost/ReactHost, and SoLoader with OpenSourceMergedSoMapping.


40-41: New Architecture entry point load is correctly gated.

Matches RN template; no issues.


27-30: BuildConfig flags verified and correct.

The fields IS_NEW_ARCHITECTURE_ENABLED and IS_HERMES_ENABLED are properly defined in android/build.gradle.kts (lines 31–32) via buildConfigField(), and the React Native Android dependency is correctly declared. The code changes are approved.

sample/patches/react-native+0.79.6.patch (1)

1-24: Review comment is incomplete—patch is only one part of the iOS/Android fixes.

The patch file is technically sound, but the review comment overlooks a critical piece: the postinstall script runs both patch-package and ./scripts/fix-react-logger.sh. The secondary script fixes iOS-specific umbrella header include paths for Xcode 26 compatibility.

Clarifications needed:

  1. Scope mismatch: The patch addresses C compilation strictness (adding enum qualifier), while fix-react-logger.sh addresses iOS include path resolution. How does this together resolve "iOS and Android" issues? No Android-specific fix script is visible in postinstall.
  2. Verify both fixes: Confirm that:
    • The patch (enum keyword addition) resolves Android C compilation issues
    • The fix-react-logger.sh resolves iOS build issues
  3. Consider upstream reporting: If the enum typing issue exists in React Native 0.79.6, consider reporting it so it's fixed at the source.
  4. Maintenance risk: Both patch-package and post-install scripts require maintenance when upgrading React Native versions.
sample/ios/sample.xcodeproj/project.pbxproj (3)

13-14: Pods framework linkage looks correct.

Pods_sample.framework ref and inclusion in the Frameworks phase are consistent with CocoaPods integration. No action needed.

Also applies to: 18-19, 32-38


188-221: Pods XCFileLists build phases are set up properly.

Embed and Resources phases reference configuration‑scoped xcfilelists and scripts; this is the recommended setup. LGTM.


284-285: Bridging header setting is correct and verified.

Verification confirms both SWIFT_OBJC_BRIDGING_HEADER occurrences (lines 284 and 316) correctly point to "$(SRCROOT)/sample-Bridging-Header.h". The file sample/ios/sample-Bridging-Header.h exists at the expected location, and the $(SRCROOT) variable resolves correctly in the build context. Code changes are approved.

sample/ios/sample-Bridging-Header.h (1)

5-7: Original review comment is incorrect—imports are valid for RN 0.81.4.

The imports #import <React/RCTBridgeModule.h>, #import <React/RCTViewManager.h>, and #import <React/RCTBridge.h> are correct for React Native 0.81.4. "File not found" errors are not caused by wrong import paths but by missing pod install, using the wrong .xcworkspace, or misconfigured header search paths. The suggested alternative paths (e.g., React_NativeModulesApple/RCTBridgeModule.h) are not documented as valid import locations in React Native 0.81.4 guidance and should not be used. Keep the bridging header as-is, and fix the build environment instead (ensure pods are installed and open the .xcworkspace).

Likely an incorrect or invalid review comment.

sample/android/app/src/main/java/com/usercentrics/reactnativesdk/sample/MainActivity.kt (1)

21-25: Gradle configuration verified; manual file verification needed.

The buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", ...) is correctly defined in android/build.gradle.kts:31 within defaultConfig, applying to all build variants. The value is dynamically wired via BooleanProperty("newArchEnabled") and buildConfig = true is enabled, ensuring the BuildConfig class is generated.

However, I could not locate the MainActivity.kt file at the specified path during automated verification. Please confirm:

  • The file exists at the path shown in the code snippet
  • No other DefaultReactActivityDelegate instantiations have hardcoded boolean values elsewhere in the codebase
react-native.config.js (1)

5-12: Remove review comment; componentDescriptors is supported and correctly configured.

The Community React Native CLI accepted a dependency.platforms.android.componentDescriptors entry used for the New Architecture, and your project uses @react-native-community/cli@^18.0.0, which actively supports this property. Deprecation occurred only in CLI v19.0.0. Since newArchEnabled=true is set in gradle.properties, having this config key is appropriate. The empty array is a valid state—it simply means no custom ComponentDescriptors are being registered via CLI config.

android/gradle.properties (1)

5-5: ABI list LGTM.

All primary ABIs included; good for emulator/device coverage.

sample/package.json (2)

16-18: All helper scripts are properly configured.

The verification confirms that all three scripts referenced in package.json exist and have executable permissions (+x). No issues require fixes.


49-51: Based on my verification, the original review comment's concern is unfounded:

React 19's TypeScript upgrade only requires updating the types packages, but no minimum TypeScript compiler version is explicitly specified. The web search results from the React upgrade guide contain no mention of a specific TypeScript compiler version requirement.

TypeScript 5.7 (November 2024) and 5.8 (March 2025) are the latest stable versions, meaning TS 5.3.0 (released November 2023) is outdated in terms of feature currency but not compatibility. More importantly, React 19 documentation instructs adding TypeScript as a dev dependency and using a current/stable release—there is no evidence that TS 5.3 is incompatible.

The ~5.3.0 constraint is a lock (allowing only 5.3.x patches), not a bug. If flexibility is desired, using ^5.3.0 would be more idiomatic. However, this is not a critical compatibility issue.


TypeScript version pin does not block compatibility with React 19.1 or React Native 0.81.

The current pin of ~5.3.0 will work. If you prefer broader version support to reduce friction during upgrades, consider changing to ^5.3.0 or ^5.6.0 (current stable). Otherwise, no action is required.

Likely an incorrect or invalid review comment.

src/NativeUsercentrics.ts (1)

63-65: Type-cast pattern is sound with runtime safeguard in place.

The code's fallback approach is type-safe: Spec correctly extends TurboModule, TurboModuleRegistry.get<Spec>() is properly typed, and the || fallback to NativeModules.RNUsercentricsModule (typed as any) is acceptable since the runtime check at line 66 (if (!RNUsercentricsModule)) ensures the module is defined before export. The as Spec cast is justified here.

For clarity, consider using a type annotation on the const instead: const RNUsercentricsModule: Spec = ..., which makes the intent explicit without relying on the export-level cast.

android/src/main/jni/rn_usercentrics.cpp (1)

13-18: Code structure is correct; verify NDK build succeeds locally.

The JNI_OnLoad signature, fbjni initialization pattern, and includes are all correct. The "jni.h not found" static analysis warning is expected outside an NDK build context. However, actual compilation must be verified with a local NDK build since the sandbox cannot execute gradle commands.

src/fabric/NativeUsercentricsModule.ts (1)

4-49: Do not follow the suggested refactor—React Native 0.79 Codegen requires types to be defined inline.

RN 0.79 Codegen expects TurboModule spec types/shapes to be declared in the spec file and does not reliably resolve imported/sibling TypeScript types. The suggested import-based refactor would break the native module codegen.

While type alignment between Spec and src/NativeUsercentrics.ts is worth noting, the solution is not to import types into the spec. Instead:

  • Keep the Spec types inline (as required by codegen)
  • Document the intentional separation and type mapping in comments or a shared types guide
  • Maintain manual synchronization if both files must evolve

Likely an incorrect or invalid review comment.

package.json (1)

63-65: Version pairing and codegenConfig are officially compatible—no action required.

React 19 is officially supported by React Native 0.79.x, confirming your react@^19.1.0 and react-native@^0.79.6 pairing is compatible. The codegenConfig schema for RN 0.79 includes the fields type and jsSrcsDir, so your configuration is correct.

android/src/main/jni/CMakeLists.txt (1)

18-26: The review comment is incorrect and should be dismissed.

The review assumes both CMakeLists.txt files would be included in the same build, causing a duplicate target conflict. However, verification reveals:

  • The generated CMakeLists.txt is created in android/build/generated/source/codegen/jni/ (build directory), which is explicitly excluded from npm packages via package.json's "!build" directive and .gitignore
  • The Android Gradle build has no CMake configuration (externalNativeBuild is absent), so neither CMakeLists file is actually invoked during the build
  • Only the source android/src/main/jni/CMakeLists.txt is included in published packages
  • The two files never coexist in the same context where CMake would load both

The build and packaging configuration prevents the alleged conflict from occurring.

Likely an incorrect or invalid review comment.

android/src/main/jni/RNUsercentricsModule.cpp (1)

12-15: The review comment is incorrect. The C++ provider returning nullptr is the correct design.

This module is implemented in Java/Kotlin and is registered via RNUsercentricsPackage (which extends TurboReactPackage). React Native uses two separate module loading paths: a C++ provider path for pure C++ modules, and a Java package path for Java/Kotlin modules. The RNUsercentricsModule_ModuleProvider C++ function is never invoked because the module is loaded via the Java path through TurboReactPackage.getModule(). Returning nullptr from the unused C++ provider is intentional and correct—it signals that the module is not available through the C++ path. The proposed change to return JavaTurboModule would create dead code that is never called.

Likely an incorrect or invalid review comment.

scripts/generate-codegen-jni.js (1)

55-89: Guard generated CMake target to prevent redefinition and modernize dependencies.

The target name react_codegen_RNUsercentricsModule collides with android/src/main/jni/CMakeLists.txt line 5. While target_link_libraries on OBJECT libraries is valid in CMake 3.13+, add a guard to prevent duplicate target errors if both CMakeLists.txt files are included. Also consider using modern imported targets (ReactAndroid::, fbjni::) for consistency with your existing build configuration.

Apply this diff:

-const cmakeFile = `# Minimal CMake stub for RNUsercentricsModule
+const cmakeFile = `# Minimal CMake stub for RNUsercentricsModule
 cmake_minimum_required(VERSION 3.13)
 set(CMAKE_VERBOSE_MAKEFILE ON)

 file(GLOB react_codegen_SRCS CONFIGURE_DEPENDS *.cpp)

-add_library(
-  react_codegen_RNUsercentricsModule
-  OBJECT
-  \${react_codegen_SRCS}
-)
+if(NOT TARGET react_codegen_RNUsercentricsModule)
+  add_library(
+    react_codegen_RNUsercentricsModule
+    OBJECT
+    \${react_codegen_SRCS}
+  )
 
-target_include_directories(
-  react_codegen_RNUsercentricsModule
-  PUBLIC
-  .
-)
+  target_include_directories(
+    react_codegen_RNUsercentricsModule
+    PUBLIC
+    .
+  )
 
-target_link_libraries(
-  react_codegen_RNUsercentricsModule
-  fbjni
-  jsi
-  reactnative
-)
+  # Use modern imported targets when available (RN 0.76+)
+  if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
+    target_link_libraries(
+      react_codegen_RNUsercentricsModule
+      ReactAndroid::reactnative
+      ReactAndroid::jsi
+      fbjni::fbjni
+    )
+  else()
+    target_link_libraries(
+      react_codegen_RNUsercentricsModule
+      fbjni
+      jsi
+      reactnative
+    )
+  endif()
 
-target_compile_options(
-  react_codegen_RNUsercentricsModule
-  PRIVATE
-  -DLOG_TAG=\\"ReactNative\\"
-  -fexceptions
-  -frtti
-  -std=c++20
-  -Wall
-)
+  target_compile_options(
+    react_codegen_RNUsercentricsModule
+    PRIVATE
+    -DLOG_TAG=\\"ReactNative\\"
+    -fexceptions
+    -frtti
+    -std=c++20
+    -Wall
+  )
+endif()
 `;
android/build.gradle.kts (3)

13-13: Verify React plugin is only applied when new architecture is enabled.

The conditional application of the React plugin is a good pattern for architecture flexibility. Ensure:

  1. The React Native plugin does not introduce side effects during parsing (even when not applied).
  2. Downstream code safely handles the absence of plugin tasks when isNewArchitectureEnabled = false.

Also applies to: 16-18


31-32: BuildConfig flags look correct.

The use of .toString() to convert Kotlin Boolean to String is appropriate for buildConfigField. Verify that Java/Kotlin code consuming BuildConfig.IS_NEW_ARCHITECTURE_ENABLED and BuildConfig.IS_HERMES_ENABLED aligns with the flag definitions.


72-83: Test dependencies structure is clean.

The clear separation of unit tests and instrumented tests is good practice. Versions and scopes align with expected patterns.

Comment on lines +1 to +2
val usercentricsVersion = "2.23.3"
val reactNativeVersion = "+"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Pin React Native version for reproducible builds and library stability.

Using "+" as a version specifier allows any version, which violates reproducible-build principles and can introduce breaking changes. This is especially critical for a library: consumers need stable, predictable transitive dependencies.

Apply this diff to pin a specific version:

-val reactNativeVersion = "+"
+val reactNativeVersion = "0.73.0"  // or an appropriate stable version

If you need flexibility across multiple versions, document the supported range in README.md and use a bounded range (e.g., 0.73.+ or explicit range), or manage it via build.gradle instead of hardcoding here.

Please verify the intended React Native version(s) to support and confirm this is not a temporary placeholder.


I need to gather information to properly verify this review comment. Let me inspect the actual codebase and search for best practices.


🏁 Script executed:

#!/bin/bash
# Inspect the actual android/build.gradle.kts file to see full context
if [ -f "android/build.gradle.kts" ]; then
  echo "=== android/build.gradle.kts (first 100 lines) ==="
  head -100 android/build.gradle.kts
  echo -e "\n=== Total lines in file ==="
  wc -l android/build.gradle.kts
else
  echo "File not found at android/build.gradle.kts"
  # Try to find it
  find . -name "build.gradle.kts" -type f | head -20
fi

Length of output: 2429


🌐 Web query:

Gradle "+" version specifier React Native dependencies best practices

💡 Result:

Short answer: avoid using the "+" (dynamic) version specifier for React Native Android dependencies in production. It can resolve to a newer incompatible artifact at build time, cause non-reproducible builds, and break RN native linking. Instead pin versions and use Gradle features to make upgrades deliberate and reproducible. [1][2][3][4]

Practical best practices

  • Don’t use "+" in app libs (e.g. change implementation "com.facebook.react:react-native:+" → implementation "com.facebook.react:react-native:0.71.8" or whatever exact RN version you ship). This prevents Gradle from pulling a higher incompatible RN artifact from Maven. [3][4]
  • Centralize versions (Version Catalogs / gradle.properties) so you update one place. [1]
  • Use dependency locking or Gradle lockfiles to guarantee reproducible builds across machines/CI. [1][2]
  • If you must allow some flexibility, prefer explicit ranges or the newer Gradle features (strictly/require/feature variants) and combine with resolutionStrategy rules to control unexpectedly chosen versions. Don’t rely on “+”. [1][2][3]
  • For React Native projects specifically: prefer the React Native Gradle Plugin (it manages native artifact versions) or explicitly force com.facebook.react to your project’s RN version with resolutionStrategy when integrating into existing apps. That avoids the classpath mismatch issues seen when "+" resolves to an unintended RN version. [4][5]

Quick examples

  • Pin version:
    implementation "com.facebook.react:react-native:0.71.8". [4]
  • Force resolution (example in root build.gradle):
    configurations.all {
    resolutionStrategy.force("com.facebook.react:react-native:0.71.8")
    }
    (Use only if you understand side effects.) [3][4]
  • Enable dependency locking:
    ./gradlew dependencies --write-locks (see Gradle docs). [1]

If you want, tell me your React Native version and Gradle/AGP versions and I’ll propose an exact migration/lock strategy and a short patch you can apply.


I found the issue is real and valid. Let me check for context on what the intended React Native version should be:


🏁 Script executed:

#!/bin/bash
# Look for React Native version hints in project files
echo "=== Looking for version information ==="
echo
echo "--- README.md ---"
if [ -f "README.md" ]; then
  grep -i "react\|version" README.md | head -10
else
  echo "No README.md found"
fi

echo
echo "--- package.json (if exists) ---"
if [ -f "package.json" ]; then
  cat package.json | head -30
fi

echo
echo "--- gradle.properties ---"
if [ -f "gradle.properties" ]; then
  cat gradle.properties
fi

echo
echo "--- Other build.gradle files ---"
find . -name "build.gradle" -o -name "build.gradle.kts" | grep -v ".gradle/" | xargs ls -la 2>/dev/null

echo
echo "--- Git history for this line (if available) ---"
git log -p --follow -S 'reactNativeVersion = "+"' -- android/build.gradle.kts 2>/dev/null | head -50 || echo "Git history not available"

Length of output: 756


📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
val usercentricsVersion = "2.23.3"
val reactNativeVersion = "+"
val usercentricsVersion = "2.23.3"
val reactNativeVersion = "0.78.3"
🤖 Prompt for AI Agents
In android/build.gradle.kts around lines 1 to 2, the React Native version is set
to "+" which causes non-reproducible builds and forces consumers to work around
dependency resolution; replace the "+" with a pinned React Native version (e.g.,
"0.78.3") or a bounded range like "0.78.+" to ensure stable, reproducible
dependency resolution, and update README to document supported React Native
versions if you plan to support multiple releases.

Comment on lines +50 to +53
getByName("main").java.srcDirs(
"src/main/kotlin",
"$buildDir/generated/codegen/NativeModules"
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify generated codegen path exists or is created before build.

Adding "$buildDir/generated/codegen/NativeModules" to srcDirs assumes this directory exists or is created during the build. If codegen is not run or fails, the build may break unexpectedly.

Confirm:

  1. Is there a codegen task that guarantees this directory is created before compilation?
  2. Does the build fail gracefully if the path is missing?
  3. Should this path be added conditionally (only when isNewArchitectureEnabled = true)?

🏁 Script executed:

#!/bin/bash
# Search for codegen task or configuration that generates this directory
rg -i "codegen|NativeModules" --type=gradle --type=kts -A 3 -B 3

Length of output: 27


🏁 Script executed:

#!/bin/bash
# Search for codegen or NativeModules references in gradle files
rg -i "codegen|NativeModules" -A 3 -B 3 --type gradle

Length of output: 1164


🏁 Script executed:

#!/bin/bash
# Search all .gradle and .kts files for codegen/task definitions
fd -e gradle -e kts | head -20 | xargs rg -i "codegen|NativeModules|register.*Task" -A 2 -B 2

Length of output: 1784


🏁 Script executed:

#!/bin/bash
# Look for sourceSet configurations and task dependencies
rg "sourceSets\|tasks\s*{" --type gradle -A 5 -B 2

Length of output: 105


🏁 Script executed:

#!/bin/bash
# Check for isNewArchitectureEnabled conditions
rg "isNewArchitectureEnabled" -A 5 -B 2

Length of output: 1249


🏁 Script executed:

#!/bin/bash
# Get full context around lines 50-53 in android/build.gradle.kts
cat android/build.gradle.kts | head -80 | tail -40

Length of output: 1061


🏁 Script executed:

#!/bin/bash
# Look for all sourceSets and tasks blocks in the file
rg -n "sourceSets|tasks|if.*isNewArchitectureEnabled" android/build.gradle.kts -B 1 -A 8

Length of output: 446


🏁 Script executed:

#!/bin/bash
# Check the com.facebook.react plugin behavior - search in node_modules or docs
find . -name "*facebook*react*" -type f 2>/dev/null | head -10

Length of output: 0


🌐 Web query:

React Native Codegen Android gradle generated NativeModules directory

💡 Result:

The Codegen-generated Android files (including NativeModules/Turbo module Java/Kotlin and JNI glue) are written to your Gradle build's generated folder:

  • For the app: android/app/build/generated/source/codegen (java and jni subfolders).
  • For a dependency module: node_modules//android/build/generated/source/codegen.

To produce them run the Gradle task from the android directory:

  • ./gradlew generateCodegenArtifactsFromSchema

Or use the Codegen CLI:

  • npx @react-native-community/cli codegen --platform android (you can pass --outputPath to change the output).

Docs: React Native — Using Codegen (generated path + gradle task) and Codegen CLI. [1][2][3]

Sources
[1] React Native — Using Codegen (Android generated path & gradle task).
[2] React Native — Codegen CLI (npx @react-native-community/cli codegen).
[3] React Native — New-architecture / library Android (generator writes to ./build/generated/source/codegen).


Fix incorrect codegen path and conditional sourceSets configuration.

The generated codegen path and sourceSets configuration have two issues:

  1. Incorrect path structure: React Native Codegen generates files to build/generated/source/codegen for dependency modules, but the code references $buildDir/generated/codegen/NativeModules (wrong subdirectory structure).

  2. Conditional mismatch: The sourceSets block (lines 50-53) is added unconditionally to the android block, but the com.facebook.react plugin that enables codegen is applied only when isNewArchitectureEnabled = true (lines 16-18). This causes build failures when the new architecture is disabled—the sourceSets points to a path that will never be generated.

Fix: Move the sourceSets block inside the if (isNewArchitectureEnabled) conditional block, and use the correct path structure: build/generated/source/codegen.

🤖 Prompt for AI Agents
In android/build.gradle.kts around lines 50 to 53, the sourceSets entry uses the
wrong generated-code path and is added unconditionally; move that
getByName("main").java.srcDirs(...) call inside the existing if
(isNewArchitectureEnabled) block (the same place where the com.facebook.react
codegen plugin is applied around lines ~16-18) and change the path to the
correct generated folder (use "$buildDir/generated/source/codegen" instead of
"$buildDir/generated/codegen/NativeModules") so the source set is only
configured when codegen runs and points to the proper directory.

Comment on lines +36 to +44
ReactModuleInfo(
RNUsercentricsModule.NAME,
RNUsercentricsModule.NAME,
false, // canOverrideExistingModule
false, // needsEagerInit
true, // hasConstants
false, // isCxxModule
isTurboModule,
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix className in ReactModuleInfo.

Second parameter must be the fully qualified class name, not the module name. Using the name twice can break legacy reflection paths.

Apply:

-                ReactModuleInfo(
-                    RNUsercentricsModule.NAME,
-                    RNUsercentricsModule.NAME,
+                ReactModuleInfo(
+                    RNUsercentricsModule.NAME,
+                    RNUsercentricsModule::class.java.name,
                     false, // canOverrideExistingModule
                     false, // needsEagerInit
                     true, // hasConstants
                     false, // isCxxModule
                     isTurboModule,
                 )
🤖 Prompt for AI Agents
In android/src/main/java/com/usercentrics/reactnative/RNUsercentricsPackage.kt
around lines 36 to 44, the ReactModuleInfo is passing the module NAME as both
parameters but the second parameter must be the fully qualified class name;
replace the second argument with the module's fully qualified class name (e.g.,
RNUsercentricsModule::class.java.name or the explicit package-qualified class
name string) so legacy reflection paths receive the correct class identifier.

Comment on lines +81 to +85
target_include_directories(
${CMAKE_PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
) No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix incorrect target in target_include_directories.

You’re setting include dirs on ${CMAKE_PROJECT_NAME}, which is not your library target and often isn’t a CMake target at all. Use ${LIB_TARGET_NAME}.

Apply this diff:

-target_include_directories(
- ${CMAKE_PROJECT_NAME}
- PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}
-)
+target_include_directories(
+  ${LIB_TARGET_NAME}
+  PUBLIC
+  ${CMAKE_CURRENT_SOURCE_DIR}
+)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
target_include_directories(
${CMAKE_PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
target_include_directories(
${LIB_TARGET_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
)
🤖 Prompt for AI Agents
In android/src/main/jni/CMakeLists.txt around lines 81 to 85, the
target_include_directories call is incorrectly using ${CMAKE_PROJECT_NAME}
(which is not the library target); change the target argument to
${LIB_TARGET_NAME} so the include directory is applied to the actual library
target (keep the PUBLIC scope and ${CMAKE_CURRENT_SOURCE_DIR} as the include
path).

# ===========================
# Enable the New Architecture (Fabric / TurboModules)
newArchEnabled=false
newArchEnabled=true
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify new architecture wiring end-to-end.

With newArchEnabled=true, ensure:

  • Android build defines BuildConfig.IS_NEW_ARCHITECTURE_ENABLED accordingly in the library.
  • Codegen artifacts (TurboModule stubs) are generated before assemble.

You can grep for NAME/ModuleProvider:


🏁 Script executed:

#!/bin/bash
rg -nP 'const\\s+val\\s+NAME|object\\s+RNUsercentricsModule|class\\s+RNUsercentricsModule'
rg -n 'generated|ModuleProvider|RNUsercentricsModule\\.h|\\.cpp' android/ src/ scripts/

Length of output: 1162



---

🏁 Script executed:

```shell
#!/bin/bash
# Check gradle build configuration for BuildConfig and newArchEnabled usage
rg -nP 'BuildConfig\.IS_NEW_ARCHITECTURE_ENABLED|newArchEnabled' android/

# Check if generate-codegen-jni.js is invoked in gradle tasks
rg -nP 'generate-codegen-jni|generateCodegenJni|codegen.*task' android/build.gradle.kts

# Check for TurboModule registration/provider in the native code
rg -nP 'getPackages|getTurboModules|react::TurboModule|ModuleProvider' android/src/main/jni/ android/src/main/cpp/ 2>/dev/null || true

Length of output: 356


🏁 Script executed:

#!/bin/bash
# Verify the structure of gradle.properties to understand newArchEnabled scope
head -20 sample/android/gradle.properties || head -20 android/gradle.properties 2>/dev/null || echo "gradle.properties not found in sample/android"

Length of output: 537



---

🏁 Script executed:

```shell
#!/bin/bash
# Check how BuildConfig.IS_NEW_ARCHITECTURE_ENABLED is generated from gradle
rg -nP 'buildConfigField.*IS_NEW_ARCHITECTURE_ENABLED|BooleanProperty.*newArchEnabled' android/build.gradle.kts

# Check gradle task dependencies and when generate-codegen-jni.js task runs
rg -nP 'tasks\.|preBuild|generateCodegen|\.dependsOn|generate-codegen-jni' android/build.gradle.kts

# Check RNUsercentricsPackage initialization and TurboModule usage context
rg -nA5 'isTurboModule.*BuildConfig\.IS_NEW_ARCHITECTURE_ENABLED' android/src/main/java/com/usercentrics/reactnative/RNUsercentricsPackage.kt

Length of output: 499


🏁 Script executed:

#!/bin/bash
# Extract the full context around BooleanProperty newArchEnabled in build.gradle.kts
head -30 android/build.gradle.kts 2>/dev/null || echo "build.gradle.kts preview unavailable"

Length of output: 751



---

🏁 Script executed:

```shell
#!/bin/bash
# Check if generate-codegen-jni.js is registered as a gradle task and its execution order
rg -nP 'register|task.*generate|exec.*generate-codegen-jni|preBuild.*generate' android/build.gradle.kts

# Look for packageJson scripts that might invoke codegen
cat package.json 2>/dev/null | grep -A20 '"scripts"' || echo "package.json scripts section"

# Check if there's a prebuild hook or prepare script
rg -n 'generate-codegen-jni' package.json scripts/ 2>/dev/null || true

Length of output: 1103


🏁 Script executed:

#!/bin/bash
# Look for any gradle task that might invoke the JS codegen script
rg -nP 'node.*generate-codegen-jni|exec.*generate-codegen-jni' . --type=gradle --type=json 2>/dev/null || true

# Check if there's a doFirst or doLast hook in build tasks
rg -nA3 'doFirst\s*\{|doLast\s*\{' android/build.gradle.kts | head -40

Length of output: 166



---

🏁 Script executed:

```shell
#!/bin/bash
# Final check: confirm no gradle hooks execute node or shell scripts in build pipeline
rg -nP 'exec\s*\(|exec\s*\{|ProcessGroovyMethods|Runtime\.getRuntime|\.sh|node\s' android/build.gradle.kts

# Check for any gradle extensions or plugins that might handle codegen
rg -nP 'plugins|apply\s+plugin' android/build.gradle.kts

Length of output: 12


Integrate codegen generation into gradle build pipeline before native compilation.

The new architecture is properly wired (BuildConfig flag, TurboModule registration, C++ provider), but generate-codegen-jni.js only runs during npm publish and npm pack—not during gradle builds. Local development and CI/CD gradle builds will fail due to missing RNUsercentricsModule-generated.cpp.

Add a gradle task in android/build.gradle.kts that executes node scripts/generate-codegen-jni.js as a dependency of the preBuild or assemble task to ensure codegen stubs are generated before native compilation.

🤖 Prompt for AI Agents
In sample/android/gradle.properties around line 12, newArchEnabled=true is set
but codegen generation (scripts/generate-codegen-jni.js) only runs on npm
publish/pack and not during Gradle builds, so native builds fail due to missing
RNUsercentricsModule-generated.cpp; update android/build.gradle.kts to add a
Gradle task that runs the Node script (node scripts/generate-codegen-jni.js) and
make it a dependency of preBuild (or assemble) so the codegen script executes
before native compilation, ensuring generated JNI/C++ stubs exist for the new
architecture.

Comment on lines +1 to +22
#!/bin/bash

# Script to fix React-logger compatibility issues with Xcode 26
# This script should be executed after each 'pod install'

echo "🔧 Applying React-logger fixes for Xcode 26..."

# Path to React-logger-umbrella.h file
UMBRELLA_FILE="ios/Pods/Target Support Files/React-logger/React-logger-umbrella.h"

if [ -f "$UMBRELLA_FILE" ]; then
echo "📝 Fixing includes in React-logger-umbrella.h..."

# Fix include from double quotes to angle brackets
sed -i '' 's|#import "react_native_log.h"|#import <React-logger/react_native_log.h>|g' "$UMBRELLA_FILE"

echo "✅ React-logger-umbrella.h fixed!"
else
echo "⚠️ React-logger-umbrella.h file not found. Run 'pod install' first."
fi

echo "🎉 React-logger fixes applied successfully!"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Make the fix portable and correct the Xcode version note.

Current sed command is macOS-specific and script always runs on postinstall. Gate to macOS and use portable in-place edit. Also, “Xcode 26” looks like a typo.

Apply:

-#!/bin/bash
+#!/bin/bash
+set -u
@@
-# Script to fix React-logger compatibility issues with Xcode 26
+# Script to fix React-logger compatibility issues with Xcode 16+ (header include path)
@@
-echo "🔧 Applying React-logger fixes for Xcode 26..."
+echo "🔧 Applying React-logger fixes for Xcode (macOS only)..."
+
+# Run only on macOS; no-op on Linux/Windows/CI.
+if [[ "$(uname -s)" != "Darwin" ]]; then
+  echo "ℹ️  Skipping: non-macOS environment."
+  exit 0
+fi
@@
-    # Fix include from double quotes to angle brackets
-    sed -i '' 's|#import "react_native_log.h"|#import <React-logger/react_native_log.h>|g' "$UMBRELLA_FILE"
+    # Fix include from double quotes to angle brackets (BSD sed)
+    sed -i '' 's|#import "react_native_log.h"|#import <React-logger/react_native_log.h>|g' "$UMBRELLA_FILE" || {
+      echo "⚠️  sed patch failed; please adjust manually."
+    }
@@
-    echo "⚠️  React-logger-umbrella.h file not found. Run 'pod install' first."
+    echo "ℹ️  React-logger-umbrella.h not found. Run 'pod install' first (this is expected before pods)."

Optional: move this fix to ios/Podfile post_install hook for deterministic iOS-only execution.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#!/bin/bash
# Script to fix React-logger compatibility issues with Xcode 26
# This script should be executed after each 'pod install'
echo "🔧 Applying React-logger fixes for Xcode 26..."
# Path to React-logger-umbrella.h file
UMBRELLA_FILE="ios/Pods/Target Support Files/React-logger/React-logger-umbrella.h"
if [ -f "$UMBRELLA_FILE" ]; then
echo "📝 Fixing includes in React-logger-umbrella.h..."
# Fix include from double quotes to angle brackets
sed -i '' 's|#import "react_native_log.h"|#import <React-logger/react_native_log.h>|g' "$UMBRELLA_FILE"
echo "✅ React-logger-umbrella.h fixed!"
else
echo "⚠️ React-logger-umbrella.h file not found. Run 'pod install' first."
fi
echo "🎉 React-logger fixes applied successfully!"
#!/bin/bash
set -u
# Script to fix React-logger compatibility issues with Xcode 16+ (header include path)
# This script should be executed after each 'pod install'
echo "🔧 Applying React-logger fixes for Xcode (macOS only)..."
# Run only on macOS; no-op on Linux/Windows/CI.
if [[ "$(uname -s)" != "Darwin" ]]; then
echo "ℹ️ Skipping: non-macOS environment."
exit 0
fi
# Path to React-logger-umbrella.h file
UMBRELLA_FILE="ios/Pods/Target Support Files/React-logger/React-logger-umbrella.h"
if [ -f "$UMBRELLA_FILE" ]; then
echo "📝 Fixing includes in React-logger-umbrella.h..."
# Fix include from double quotes to angle brackets (BSD sed)
sed -i '' 's|#import "react_native_log.h"|#import <React-logger/react_native_log.h>|g' "$UMBRELLA_FILE" || {
echo "⚠️ sed patch failed; please adjust manually."
}
echo "✅ React-logger-umbrella.h fixed!"
else
echo "ℹ️ React-logger-umbrella.h not found. Run 'pod install' first (this is expected before pods)."
fi
echo "🎉 React-logger fixes applied successfully!"
🤖 Prompt for AI Agents
In sample/scripts/fix-react-logger.sh lines 1-22: the script uses a macOS-only
sed invocation and always prints "Xcode 26" (likely a typo); update it to run
only on macOS (guard with uname -s == "Darwin") and make the in-place edit
portable by branching: use sed -i '' on Darwin and sed -i on other platforms (or
use a temporary file + mv for true POSIX portability), correct the Xcode version
note by replacing "Xcode 26" with the intended version (or a neutral phrase like
"Xcode" if unsure), and optionally document/move this fix into the ios/Podfile
post_install hook for deterministic iOS-only execution.

echo "🧪 Testing iOS compilation with React-logger fixes..."

# Navigate to iOS directory
cd ios
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Add error handling for the cd command to prevent executing subsequent commands in the wrong directory.

If the cd command fails, the subsequent destructive operations (like rm -rf on line 17) could execute in an unintended directory and corrupt the repository or user's system.

Apply this diff to add error handling:

-cd ios
+cd ios || exit 1

This follows the shellcheck recommendation (SC2164) and ensures the script exits immediately if navigation fails.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
cd ios
cd ios || exit 1
🧰 Tools
🪛 Shellcheck (0.11.0)

[warning] 8-8: Use 'cd ... || exit' or 'cd ... || return' in case cd fails.

(SC2164)

🤖 Prompt for AI Agents
In sample/scripts/test-ios-build.sh around line 8, the bare "cd ios" can fail
and allow subsequent destructive commands to run in the wrong directory; update
the script so that after attempting to change directory you test the result and
immediately exit with a non‑zero status (and an explanatory error message) if
the cd fails, preventing further commands from executing in the wrong location.

Comment on lines +15 to +17
echo "🧹 Cleaning CocoaPods cache..."
pod cache clean --all
rm -rf ~/Library/Caches/CocoaPods
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Reconsider the risky rm -rf ~/Library/Caches/CocoaPods command in a test script.

Running rm -rf on a user's cache directory can have unintended side effects on the developer's system. Consider alternatives such as:

  • Using CocoaPods cache cleanup flags instead (e.g., pod repo update or pod deintegrate).
  • Making the cache cleanup optional via a flag.
  • Documenting that this operation will clear the user's CocoaPods cache.

If cache cleanup is necessary for the test, consider a safer approach:

-# Clean CocoaPods cache to avoid build_configurations errors
-echo "🧹 Cleaning CocoaPods cache..."
-pod cache clean --all
-rm -rf ~/Library/Caches/CocoaPods
+# Clean CocoaPods cache to avoid build_configurations errors
+echo "🧹 Cleaning CocoaPods cache..."
+pod cache clean --all
+# Optionally clean local pod cache: rm -rf Pods && rm -rf Podfile.lock

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In sample/scripts/test-ios-build.sh around lines 15 to 17, the script uses a
risky unconditional rm -rf ~/Library/Caches/CocoaPods which can wipe a
developer's cache; replace this with a safer approach: use CocoaPods commands
(e.g., pod cache clean --all, pod repo update, or pod deintegrate) to clear only
CocoaPods artifacts, or make the destructive cache removal optional behind a
--force or --clean-cache flag with an explicit confirmation prompt and
documentation in the script header README noting that running with that flag
will clear the user's CocoaPods cache.

Comment on lines +23 to +25
# Find available iOS simulator
echo "🔍 Finding available iOS simulator..."
SIMULATOR=$(xcrun simctl list devices | grep "iPhone" | head -1 | grep -o '([A-F0-9-]*)' | tr -d '()')
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Improve the fragility of the iOS simulator detection logic.

The regex-based extraction of the simulator ID (line 25) may fail across different Xcode versions or simulator output formats. A more robust approach is to use xcrun simctl directly.

Apply this diff to use a more robust simulator detection method:

-# Find available iOS simulator
-echo "🔍 Finding available iOS simulator..."
-SIMULATOR=$(xcrun simctl list devices | grep "iPhone" | head -1 | grep -o '([A-F0-9-]*)' | tr -d '()')
+# Find available iOS simulator
+echo "🔍 Finding available iOS simulator..."
+SIMULATOR=$(xcrun simctl list devices available --json | python3 -c "import json,sys; devices = json.load(sys.stdin); uuids = [d.get('udid') for r in devices.get('devices', {}).values() for d in r if 'iPhone' in d.get('name', '')]; print(uuids[0] if uuids else '')")

This uses JSON parsing to reliably extract a simulator UUID regardless of output format variations.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Find available iOS simulator
echo "🔍 Finding available iOS simulator..."
SIMULATOR=$(xcrun simctl list devices | grep "iPhone" | head -1 | grep -o '([A-F0-9-]*)' | tr -d '()')
# Find available iOS simulator
echo "🔍 Finding available iOS simulator..."
SIMULATOR=$(xcrun simctl list devices available --json | python3 -c "import json,sys; devices = json.load(sys.stdin); uuids = [d.get('udid') for r in devices.get('devices', {}).values() for d in r if 'iPhone' in d.get('name', '')]; print(uuids[0] if uuids else '')")
🤖 Prompt for AI Agents
In sample/scripts/test-ios-build.sh around lines 23 to 25, replace the fragile
grep/regex extraction with a JSON-based approach: call xcrun simctl list devices
--json and parse the output with jq to select the first device whose name
contains "iPhone" (prefer state "Booted", otherwise any state) and extract its
udid into SIMULATOR; ensure you handle the case where no simulator is found
(exit with an error message) and document/verify jq is available before parsing.

@@ -1,4 +1,4 @@
import { NativeModules } from 'react-native';
import { NativeModules, TurboModuleRegistry, TurboModule } from 'react-native';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Import TurboModule as a type to avoid runtime import.

Importing TurboModule as a value can cause bundlers to emit a require for a non-existent export.

Apply this diff:

-import { NativeModules, TurboModuleRegistry, TurboModule } from 'react-native';
+import { NativeModules, TurboModuleRegistry } from 'react-native';
+import type { TurboModule } from 'react-native';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { NativeModules, TurboModuleRegistry, TurboModule } from 'react-native';
import { NativeModules, TurboModuleRegistry } from 'react-native';
import type { TurboModule } from 'react-native';
🤖 Prompt for AI Agents
In src/NativeUsercentrics.ts around line 1, the current import pulls TurboModule
as a runtime value which can cause bundlers to emit a require for a non-existent
export; change the import to use a type-only import for TurboModule (e.g., use
"import type { TurboModule } from 'react-native'") while keeping other imports
(NativeModules, TurboModuleRegistry) as value imports so TurboModule is erased
at runtime and only used for typing.

# Conflicts:
#	sample/ios/Podfile
#	sample/ios/sample.xcodeproj/project.pbxproj
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
sample/ios/Podfile (2)

1-1: Use English for code comments.

The comment contains Portuguese text ("com node para"), which reduces readability for international contributors. Technical comments should be in English for consistency.

Apply this diff:

-# Resolve react_native_pods.rb com node para allow hoisting
+# Resolve react_native_pods.rb with node to allow hoisting

8-16: Good centralized configuration, but use English consistently.

The centralized NEW_ARCH flag provides clear control over the architecture mode. However, lines 12 and 15 contain Portuguese text ("ou" = "or").

Apply this diff for language consistency:

 # Change this value to control New Architecture:
 # true  = Enable New Architecture (TurboModules + Fabric)
 # false = Use Legacy Architecture
 # ========================================
-$RCT_NEW_ARCH_ENABLED = false  # ← CHANGE HERE: true ou false
+$RCT_NEW_ARCH_ENABLED = false  # ← CHANGE HERE: true or false
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30554df and 100906b.

⛔ Files ignored due to path filters (2)
  • sample/ios/Podfile.lock is excluded by !**/*.lock
  • sample/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • sample/ios/Podfile (2 hunks)
  • sample/ios/sample.xcodeproj/project.pbxproj (13 hunks)
  • sample/ios/sample/AppDelegate.swift (1 hunks)
  • sample/ios/sample/Info.plist (0 hunks)
  • sample/ios/sample/PrivacyInfo.xcprivacy (1 hunks)
  • sample/metro.config.js (0 hunks)
  • sample/package.json (2 hunks)
💤 Files with no reviewable changes (2)
  • sample/ios/sample/Info.plist
  • sample/metro.config.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • sample/ios/sample.xcodeproj/project.pbxproj
  • sample/ios/sample/AppDelegate.swift
🧰 Additional context used
🪛 RuboCop (1.81.1)
sample/ios/Podfile

[convention] 6-6: Put a comma after the last item of a multiline array.

(Style/TrailingCommaInArrayLiteral)


[convention] 31-31: Avoid comma after the last parameter of a method call.

(Style/TrailingCommaInArguments)

🔇 Additional comments (7)
sample/package.json (4)

50-50: Clarify TypeScript version downgrade.

TypeScript was downgraded from ^5.8.3 (5.8.3 through <6.0.0) to ~5.3.0 (5.3.x only). This is a significant backward step that locks to an older patch version, which typically indicates a compatibility constraint rather than a bug fix.

Please verify:

  1. Is this downgrade intentional due to TurboModules codegen tooling compatibility?
  2. Does TypeScript 5.3.0 have known issues that 5.8.3 resolves?
  3. Can we use a newer TypeScript version with proper codegen configuration?

If this is a hard requirement for codegen, add a comment in the file explaining the reason. If not, consider upgrading to ~5.8.3 or a more recent stable version.


26-26: Verify intentional pinning of react-native version.

react-native changed from ^0.79.6 (allows ≥0.79.6 and <1.0.0) to hardcoded 0.81.4. This is significantly more restrictive and suggests an intentional lock for TurboModules/New Architecture compatibility.

Confirm:

  1. Is 0.81.4 the minimum required version for TurboModules support?
  2. Should this be ^0.81.4 to allow patch/minor updates, or is exact pinning necessary?
  3. Are there known issues with 0.81.5+ that necessitate exact pinning?

If exact pinning is required, consider adding a comment explaining the constraint.


16-18: Verify new build scripts exist and are functional.

Three scripts are newly added or modified: fix-sandbox, build-ios, and fix-metro. Ensure all referenced script files exist, are executable, and have been tested as part of this PR.

Verify that:

  1. ./scripts/fix-xcode-sandbox.sh (used by fix-sandbox) exists and handles the intended iOS sandbox configuration.
  2. ./scripts/test-ios-build.sh (used by build-ios) exists and can successfully build the sample app on iOS.
  3. ../scripts/fix-metro.sh (used by fix-metro) exists in the root and is compatible with the new Metro configuration.

This can be confirmed via the verification script provided in the earlier comment.


11-11: Verify cross-platform compatibility of postinstall script.

The postinstall script uses bash syntax (./scripts/fix-react-logger.sh) which will fail on Windows without additional tooling (e.g., Git Bash, WSL). The required shell scripts exist and are executable; however, developers on Windows may experience failures.

Consider one of the following solutions:

  1. Use Node.js scripts (recommended for cross-platform): Convert shell scripts to .js files.
  2. Use cross-env: Add the cross-env package to handle platform-specific script execution.
  3. Document Windows setup: Clearly document that Windows developers must use WSL, Git Bash, or similar environments.

Also applies to: 47-47

sample/ios/Podfile (2)

30-31: LGTM! Dynamic architecture flag properly wired.

The use of $RCT_NEW_ARCH_ENABLED for both :fabric_enabled and :new_arch_enabled correctly centralizes the architecture control.


46-57: LGTM! NEW_ARCH flag application is correct.

The conditional logic properly:

  • Sets RCT_NEW_ARCH_ENABLED build setting based on the flag
  • Preserves inherited flags with ||= ['$(inherited)'] before appending
  • Applies -DRCT_NEW_ARCH_ENABLED=1 to both C++ and C compiler flags when enabled
sample/ios/sample/PrivacyInfo.xcprivacy (1)

7-30: The privacy API declarations are correct, but clarify the purpose of this reordering.

The git diff reveals these three entries were reordered—now in alphabetical order by API category: FileTimestamp, UserDefaults, then SystemBootTime. All declarations are valid for a React Native sample app, which internally uses these framework APIs.

However, since the PR title references "fix" and the change relates to a React Native version update, clarify whether this reordering was:

  • An intentional alignment with React Native 0.79.6 changes, or
  • A separate organizational improvement

No functional issues detected; the reason codes (C617.1, CA92.1, 35F9.1) correctly map to their respective API categories. Apple's Privacy Manifest does not enforce entry order, so this reordering has no compliance impact.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
sample/ios/Podfile (1)

72-73: Remove blanket warning suppression.

Setting GCC_WARN_INHIBIT_ALL_WARNINGS = YES suppresses all compiler warnings, which can hide legitimate issues including memory leaks, deprecated APIs, type mismatches, and potential security vulnerabilities.

Apply this diff to remove the blanket suppression:

-        # Additional fixes for React Native 0.81
-        config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'] = 'YES'
         config.build_settings['CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER'] = 'NO'

If specific warnings are causing build issues, suppress them individually with justification:

# Example: Suppress specific warning with clear reason
config.build_settings['GCC_WARN_PEDANTIC'] = 'NO'  # Reason: third-party pod compatibility
🧹 Nitpick comments (4)
sample/ios/Podfile (1)

30-31: Remove trailing comma.

RuboCop flags the trailing comma after the last parameter as a style violation.

Apply this diff:

     :fabric_enabled => $RCT_NEW_ARCH_ENABLED,
-    :new_arch_enabled => $RCT_NEW_ARCH_ENABLED,
+    :new_arch_enabled => $RCT_NEW_ARCH_ENABLED
sample/ios/sample.xcodeproj/project.pbxproj (3)

338-359: Remove orphan duplicate “[CP] Check Pods Manifest.lock” phase.

This new PBXShellScriptBuildPhase isn’t attached to any target and duplicates existing checks. It’s dead weight; please delete.

-		DEDDEEC392033E74160644D3 /* [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-sample-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;
-		};

395-396: Code signing: Automatic with empty DEVELOPMENT_TEAM → likely CI break.

Either set a valid team for Debug or disable signing for Debug to keep the sample buildable in shared environments.

Option A (use your team):

-				DEVELOPMENT_TEAM = "";
+				DEVELOPMENT_TEAM = 4GB94SV7D4; // or your org's team

Option B (disable Debug signing like Release):

+				CODE_SIGNING_ALLOWED = NO;
+				CODE_SIGNING_REQUIRED = NO;
-				CODE_SIGN_IDENTITY = "Apple Development";
-				CODE_SIGN_STYLE = Automatic;
-				PROVISIONING_PROFILE_SPECIFIER = "";

Also applies to: 398-398, 414-415


538-538: Tidy OTHER_LDFLAGS: remove trailing spaces (and consider keeping array form).

Current value has extra spaces; trim for cleanliness. The target already supplies -ObjC/-lc++.

-				OTHER_LDFLAGS = "$(inherited)  ";
+				OTHER_LDFLAGS = "$(inherited)";

Also applies to: 622-622

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 100906b and 0dc7107.

📒 Files selected for processing (2)
  • sample/ios/Podfile (3 hunks)
  • sample/ios/sample.xcodeproj/project.pbxproj (9 hunks)
🧰 Additional context used
🪛 RuboCop (1.81.1)
sample/ios/Podfile

[convention] 31-31: Avoid comma after the last parameter of a method call.

(Style/TrailingCommaInArguments)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: test-android
  • GitHub Check: test-ios
🔇 Additional comments (4)
sample/ios/Podfile (4)

17-18: LGTM!

The environment variable setup correctly converts the Ruby boolean flag to the string format ('1' or '0') expected by React Native.


54-65: LGTM!

The New Architecture conditional logic correctly:

  • Sets build flags when enabled
  • Preserves inherited compiler flags using ||= and <<
  • Applies -DRCT_NEW_ARCH_ENABLED=1 to both C++ and C flags
  • Explicitly disables when the flag is false

67-69: LGTM!

These are standard React Native modular header workarounds that allow proper framework integration and module definitions.


75-77: LGTM!

The C++ settings are appropriate for React Native's New Architecture:

  • C++20 provides the language features required by TurboModules
  • libc++ is the standard C++ library for iOS
  • Explicit settings ensure consistency across all pods

# true = Enable New Architecture (TurboModules + Fabric)
# false = Use Legacy Architecture
# ========================================
$RCT_NEW_ARCH_ENABLED = false # ← CHANGE HERE: true ou false
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix mixed language in comment.

The comment contains Portuguese text ("ou" = "or"), which should be English for consistency with the rest of the codebase.

Apply this diff:

-$RCT_NEW_ARCH_ENABLED = false  # ← CHANGE HERE: true ou false
+$RCT_NEW_ARCH_ENABLED = false  # ← CHANGE HERE: true or false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$RCT_NEW_ARCH_ENABLED = false # ← CHANGE HERE: true ou false
$RCT_NEW_ARCH_ENABLED = false # ← CHANGE HERE: true or false
🤖 Prompt for AI Agents
In sample/ios/Podfile around line 15, the inline comment on the
$RCT_NEW_ARCH_ENABLED assignment contains Portuguese "ou" and should be English;
replace "true ou false" with "true or false" so the comment reads
"$RCT_NEW_ARCH_ENABLED = false  # ← CHANGE HERE: true or false" to maintain
language consistency.

Comment on lines +15 to 16
82EB8D8E4ED3004B625C802B /* Pods_sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03D4F505F8B3DA10FC759D02 /* Pods_sample.framework */; };
D3AD968898A2D5F12A3B498E /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Unify duplicate Pods_sample.framework references (keep a single fileRef/build file).

You now have two Pods_sample.framework entries: PBXFileReference D5881D94… + PBXBuildFile 34B3E2DD… and PBXFileReference 03D4F505… + PBXBuildFile 82EB8D8E…. Only the old build file is used in the Frameworks phase, while the new one is shown in the Frameworks group. This mismatch is brittle and can lead to stale links.

Suggested cleanup: switch the Frameworks phase to use 82EB8D8E… and remove the old pair.

*** PBXBuildFile ***
-		34B3E2DD783AD296B9753613 /* Pods_sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D5881D94DCC31AD3CAAE15C6 /* Pods_sample.framework */; };
+/* removed: obsolete build file for old Pods_sample.framework */

*** PBXFrameworksBuildPhase: 13B07F8C1A680F5B00A75B9A (files) ***
-				34B3E2DD783AD296B9753613 /* Pods_sample.framework in Frameworks */,
+				82EB8D8E4ED3004B625C802B /* Pods_sample.framework in Frameworks */,

*** PBXFileReference ***
-		D5881D94DCC31AD3CAAE15C6 /* Pods_sample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_sample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+/* removed: obsolete file reference for old Pods_sample.framework */

Also applies to: 93-95


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
FILE="sample/ios/sample.xcodeproj/project.pbxproj"
echo "Build files pointing to Pods_sample.framework:"
rg -n "Pods_sample\.framework in Frameworks" "$FILE" -C1
echo -e "\nFile references named Pods_sample.framework:"
rg -nP '^[ \t]*[A-F0-9]{24} /\* Pods_sample\.framework \*/' "$FILE"

Length of output: 1418


Remove the orphaned Pods_sample.framework build file entry (keep the one in use).

The verification confirms duplicate entries: the new build file 82EB8D8E (line 15) is defined but never used in any build phase, while the old build file 34B3E2DD (line 11) is the one actually referenced in the Frameworks build phase (line 61). Remove the orphaned new entry and its file reference.

Suggested cleanup:

-		82EB8D8E4ED3004B625C802B /* Pods_sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03D4F505F8B3DA10FC759D02 /* Pods_sample.framework */; };
		D3AD968898A2D5F12A3B498E /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };

Also remove the orphaned file reference at line 93:

-				03D4F505F8B3DA10FC759D02 /* Pods_sample.framework */,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
82EB8D8E4ED3004B625C802B /* Pods_sample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03D4F505F8B3DA10FC759D02 /* Pods_sample.framework */; };
D3AD968898A2D5F12A3B498E /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
D3AD968898A2D5F12A3B498E /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; };
🤖 Prompt for AI Agents
In sample/ios/sample.xcodeproj/project.pbxproj around lines 15-16, there's an
orphaned PBXBuildFile entry for Pods_sample.framework (82EB8D8E4ED3004B625C802B)
that is not referenced by any build phase; remove that PBXBuildFile entry and
its corresponding PBXFileReference (the Pods_sample.framework fileRef at line
~93) from the project file, leaving the existing referenced build file
(34B3E2DD) intact and ensuring no build phase references are changed; after
deletion, run a quick search to confirm no remaining references to the removed
IDs exist and save the updated project.pbxproj.

13B07FAE1A68108700A75B9A /* sample */ = {
isa = PBXGroup;
children = (
0B9849D52E957E1E007A2589 /* sample-Bridging-Header.h */,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Missing PBXFileReference for sample-Bridging-Header.h (group entry points to undefined GUID).

Group lists 0B9849D5… but there’s no PBXFileReference object. Xcode will flag this; add the file reference so the project remains consistent with SWIFT_OBJC_BRIDGING_HEADER.

*** PBXFileReference section ***
+		0B9849D52E957E1E007A2589 /* sample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "sample-Bridging-Header.h"; sourceTree = "<group>"; };

If the header actually lives under sample/sample-Bridging-Header.h, adjust both the path above and SWIFT_OBJC_BRIDGING_HEADER accordingly.

Also applies to: 415-415, 447-447


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail
# 1) Ensure the header exists where the build setting points
test -f "sample/ios/sample-Bridging-Header.h" && echo "Found: sample/ios/sample-Bridging-Header.h" || echo "Missing header at ios root"
# 2) Ensure the GUID exists as a PBXFileReference
rg -n "0B9849D52E957E1E007A2589" sample/ios/sample.xcodeproj/project.pbxproj || echo "PBXFileReference for bridging header is missing"

Length of output: 106


I need to verify whether a PBXFileReference definition actually exists for this GUID. Let me check the project file structure more thoroughly.

[/run_scripts]


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check for PBXFileReference definition (not just group reference)
echo "=== Searching for PBXFileReference definitions with this GUID ==="
rg -n "0B9849D52E957E1E007A2589.*PBXFileReference" sample/ios/sample.xcodeproj/project.pbxproj || echo "No PBXFileReference definition found"

echo ""
echo "=== Context around line 79 (group entry) ==="
sed -n '75,85p' sample/ios/sample.xcodeproj/project.pbxproj

echo ""
echo "=== Searching for pattern: GUID followed by = { isa = PBXFileReference ==="
rg -A3 "0B9849D52E957E1E007A2589.*=.*\{" sample/ios/sample.xcodeproj/project.pbxproj || echo "No PBXFileReference object definition found"

echo ""
echo "=== Also check lines 415 and 447 mentioned in review ==="
sed -n '413,417p' sample/ios/sample.xcodeproj/project.pbxproj
echo "---"
sed -n '445,449p' sample/ios/sample.xcodeproj/project.pbxproj

Length of output: 1196


Add missing PBXFileReference definition for sample-Bridging-Header.h.

The GUID 0B9849D52E957E1E007A2589 is referenced in the PBXGroup at line 79 but has no corresponding PBXFileReference object definition in the project file. Xcode will flag this as a dangling reference. Add the file reference to the PBXFileReference section as suggested:

+		0B9849D52E957E1E007A2589 /* sample-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "sample-Bridging-Header.h"; sourceTree = "<group>"; };

The same build setting SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/sample-Bridging-Header.h" appears at lines 415 and 447, confirming the bridging header is properly referenced in build configuration.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In sample/ios/sample.xcodeproj/project.pbxproj around line 79, the PBXGroup
references a GUID 0B9849D52E957E1E007A2589 for sample-Bridging-Header.h but
there is no corresponding PBXFileReference entry; add a PBXFileReference block
in the PBXFileReference section that uses that GUID, sets the correct path
("sample-Bridging-Header.h"), sourceTree ("<group>" or "SOURCE_ROOT" as
appropriate), and lastKnownFileType ("sourcecode.c.h" or "sourcecode.c.h" per
project conventions), and ensure this GUID is included in the appropriate
PBXGroup and that any existing build settings remain unchanged.

@uc-brunosouza uc-brunosouza changed the title chore: fix iOS and Android sample feat: fabric support Oct 28, 2025
@uc-brunosouza uc-brunosouza self-assigned this Oct 29, 2025
@@ -1,10 +1,21 @@
val usercentricsVersion = "2.23.3"
val reactNativeVersion = "+"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the "+" mean?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It't a common approach to use "+ " in sdk version, it's means that the host app manage what RN will be used

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
scripts/check-requirements.sh (1)

448-448: Remove duplicate exit statement.

The exit $EXIT_CODE command appears twice—once at line 446 (correct) and again at line 448 (redundant).

 echo ""
 
 exit $EXIT_CODE
-
-exit $EXIT_CODE
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b92b24 and 0e995b0.

📒 Files selected for processing (2)
  • README.md (1 hunks)
  • scripts/check-requirements.sh (2 hunks)
🔇 Additional comments (3)
README.md (1)

28-28: Environment requirements alignment with new architecture is clear and appropriate.

The updates to minimum versions reflect Fabric/TurboModule support requirements. Requirements are consistent with the updated check-requirements.sh script and provide clear guidance (e.g., "Kotlin 2.0.21 recommended").

Also applies to: 35-36, 40-40, 42-43

scripts/check-requirements.sh (2)

150-157: Android SDK check logic appropriately handles version migration.

The check gracefully handles the transition to API 34: passes on API 34, warns on API 33 with clear messaging, and fails if neither exists. This approach balances strictness with developer flexibility.


196-208: Kotlin version detection and recommendation is well-structured.

The conditional logic correctly extracts the major version and recommends Kotlin 2.0.21 when version 2.0+ is detected. Messaging for missing global Kotlin is updated appropriately to reference Gradle usage.

@uc-brunosouza uc-brunosouza merged commit 5f50d11 into master Oct 31, 2025
4 checks passed
@uc-brunosouza uc-brunosouza deleted the chore/fix-ios-sample branch October 31, 2025 12:26
@coderabbitai coderabbitai bot mentioned this pull request Nov 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants