diff --git a/.eslintignore b/.eslintignore index 298a2ddc2..3a9c0c57b 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,8 +1,10 @@ # Ignore build generated dir dist -# Ignore sample folder +# Ignore standalone apps sample +sample-new-architecture +test/perf/TestApp* # Ignore dangerfile -dangerfile.js \ No newline at end of file +dangerfile.js diff --git a/.github/workflows/buildandtest.yml b/.github/workflows/buildandtest.yml index 9c8bfc13c..0524ff04a 100644 --- a/.github/workflows/buildandtest.yml +++ b/.github/workflows/buildandtest.yml @@ -14,7 +14,8 @@ jobs: steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 - + with: + node-version: 14 - uses: actions/cache@v3 id: cache with: @@ -42,12 +43,50 @@ jobs: - name: Lint run: yarn lint + job_lint_sample_new_arch: + name: Lint Sample + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/cache@v3 + id: cache + with: + path: sample-new-architecture/node_modules + key: ${{ runner.os }}-${{ github.sha }} + - name: Install Dependencies + if: steps.cache.outputs['cache-hit'] != 'true' + run: yarn install + working-directory: sample-new-architecture + - name: Lint Sample + run: yarn lint + working-directory: sample-new-architecture + + job_check_integrity: + name: Check package integrity + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/cache@v3 + id: cache + with: + path: node_modules + key: ${{ runner.os }}-${{ github.sha }} + - name: Save initial lock file + run: cp yarn.lock yarn.lock.initial + - name: Install Dependencies (update lock if necessary) + run: yarn install + - name: Check lock file integrity + run: | + ["$(diff yarn.lock.initial yarn.lock)" -eq ""] + job_build: name: Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 + with: + node-version: 14 - uses: actions/cache@v3 id: cache with: diff --git a/.github/workflows/codegen.yml b/.github/workflows/codegen.yml new file mode 100644 index 000000000..05a8f9718 --- /dev/null +++ b/.github/workflows/codegen.yml @@ -0,0 +1,37 @@ +name: Codegen + +on: + push: + branches: + - main + - release/** + pull_request: + +jobs: + codegen: + runs-on: ubuntu-latest + strategy: + matrix: + platform: ["android"] # "ios" will be added after codegen is fixed + include: + - platform: android + command: | + cd sample-new-architecture/android + ./gradlew generateCodegenArtifactsFromSchema + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: 16 + - uses: actions/cache@v3 + id: cache + with: + path: sample-new-architecture/node_modules + key: ${{ runner.os }}-${{ github.sha }} + - name: Install Dependencies + if: steps.cache.outputs['cache-hit'] != 'true' + run: | + cd sample-new-architecture + yarn install + - name: Codegen + run: ${{ matrix.command }} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index d0511a3eb..749e93dbb 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -5,6 +5,10 @@ on: branches: [main] pull_request: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + env: SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} @@ -17,7 +21,7 @@ jobs: with: access_token: ${{ github.token }} - device-test: + sample: # Android emulator said to perform best with macos HAXM runs-on: macos-latest strategy: @@ -29,10 +33,6 @@ jobs: - platform: ios runtime: 'latest' device: 'iPhone 14' - env: - PLATFORM: ${{ matrix.platform }} - RUNTIME: ${{ matrix.runtime }} - DEVICE: ${{ matrix.device }} steps: - uses: actions/checkout@v3 @@ -41,9 +41,6 @@ jobs: java-version: '11' distribution: 'adopt' - - name: Install Global Dependencies - run: yarn global add @sentry/cli yalc - - name: NPM cache uses: actions/cache@v3 id: deps-cache @@ -70,17 +67,6 @@ jobs: - name: Build SDK run: yarn build - - name: Package SDK - run: yalc publish - - - name: Prepare sample for testing - working-directory: ./sample - run: sh ./scripts/prepareConfigsForTesting.sh - - - name: Install SDK in sample - working-directory: ./sample - run: yalc add @sentry/react-native - - name: Install Sample Dependencies if: ${{ steps.deps-cache.outputs['cache-hit'] != 'true' }} working-directory: ./sample @@ -88,10 +74,9 @@ jobs: - run: pod install if: ${{ matrix.platform == 'ios' }} - working-directory: ./sample/ios env: - # TEST env var is used in podfile to determine whether to include the sentry SDK from relative path or node_modules. - TEST: true + PRODUCTION: 1 + working-directory: ./sample/ios - name: Build ${{ matrix.platform }} sample app if: ${{ env.SENTRY_AUTH_TOKEN != null }} @@ -124,45 +109,123 @@ jobs: build fi - - name: Start Appium Server - working-directory: ./sample - run: yarn run appium --log-timestamp --log-no-colors --log appium.${{ matrix.platform }}.log & - - # Wait until the Appium server starts. - - name: Check Appium Server - uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd # pin@v2 + metrics: + runs-on: macos-latest + strategy: + # we want that the matrix keeps running, default is to cancel them if it fails. + fail-fast: false + matrix: + rn-architecture: ['legacy', 'new'] + platform: ["ios", "android"] + include: + - platform: ios + name: iOS + appPlain: test/perf/test-app-plain.ipa + - platform: android + name: Android + appPlain: test/perf/TestAppPlain/android/app/build/outputs/apk/release/app-release.apk + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 with: - timeout_seconds: 60 - max_attempts: 10 - command: curl --output /dev/null --silent --head --fail http://127.0.0.1:4723/sessions - - - name: Run tests on Android - if: ${{ matrix.platform == 'android' }} - uses: reactivecircus/android-emulator-runner@50986b1464923454c95e261820bc626f38490ec0 # pin@v2 + node-version: "14" + - uses: actions/setup-java@v3 with: - api-level: 29 - emulator-options: -accel on -no-snapshot -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -camera-front none -timezone US/Pacific - working-directory: sample - script: | - # Collect logs - adb logcat '*:D' 2>&1 >adb.log & - adb devices -l - - yarn test --verbose - - - name: Run tests on iOS - if: ${{ matrix.platform == 'ios' }} - working-directory: ./sample - run: yarn test --verbose - - - name: Upload logs - if: ${{ always() }} - uses: actions/upload-artifact@v3 + java-version: "11" + distribution: "adopt" + - name: Install Global Dependencies + run: yarn global add react-native-cli @sentry/cli yalc + - uses: actions/cache@v3 + id: deps-cache with: - name: ${{ matrix.platform }}-logs path: | - ./sample/*.log - ./sample/*.png + node_modules + test/perf/TestAppSentry/node_modules + key: ${{ github.workflow }}-${{ github.job }}-${{ hashFiles('yarn.lock', 'test/perf/TestAppSentry/yarn.lock') }} + - name: Install Dependencies + if: steps.deps-cache.outputs['cache-hit'] != 'true' + run: yarn install + - name: Build SDK + run: yarn build + - name: Package SDK + run: yalc publish + - uses: actions/setup-node@v3 + with: + node-version: "16" + - uses: actions/cache@v3 + id: app-plain-cache + with: + path: ${{ matrix.appPlain }} + # if the whole plain app folder is hashed the cache is never hit as there are files generated in the folder + # the cache key is calculated both at cache retrieval and save time + # hashFiles fails when there are rn android new arch generated files in the folder (exact reason unknown) + key: ${{ github.workflow }}-${{ github.job }}-appplain-${{ matrix.platform }}-${{ matrix.rn-architecture }}-${{ hashFiles('test/perf/TestAppPlain/yarn.lock') }} + - name: Build app plain + if: steps.app-plain-cache.outputs['cache-hit'] != 'true' + working-directory: ./test/perf/TestAppPlain + run: | + yarn install + cd ${{ matrix.platform }} + if [[ "${{ matrix.platform }}" == "android" ]]; then + if [[ ${{ matrix.rn-architecture }} == 'new' ]]; then + perl -i -pe's/newArchEnabled=false/newArchEnabled=true/g' gradle.properties + fi + ./gradlew assembleRelease + else + export PRODUCTION=1 + if [[ ${{ matrix.rn-architecture }} == 'new' ]]; then + export RCT_NEW_ARCH_ENABLED=1 + fi + pod install + cd ../.. + fastlane build_perf_test_app_plain + fi + env: + APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_KEY: ${{ secrets.APP_STORE_CONNECT_KEY }} + FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} + MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} + - name: Build app with Sentry + working-directory: ./test/perf/TestAppSentry + run: | + yalc add @sentry/react-native + yarn install + cd ${{ matrix.platform }} + if [[ "${{ matrix.platform }}" == "android" ]]; then + if [[ ${{ matrix.rn-architecture }} == 'new' ]]; then + perl -i -pe's/newArchEnabled=false/newArchEnabled=true/g' gradle.properties + fi + ./gradlew assembleRelease + else + export PRODUCTION=1 + if [[ ${{ matrix.rn-architecture }} == 'new' ]]; then + export RCT_NEW_ARCH_ENABLED=1 + fi + pod install + cd ../.. + fastlane build_perf_test_app_sentry + cd TestAppSentry + fi + # Remove after build so that the cache isn't invaldiated due to the changes in yarn.lock. + yarn remove @sentry/react-native + env: + APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} + APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} + APP_STORE_CONNECT_KEY: ${{ secrets.APP_STORE_CONNECT_KEY }} + FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} + MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} + - name: Collect apps metrics + uses: getsentry/action-app-sdk-overhead-metrics@v1 + with: + name: ${{ matrix.name }} (${{ matrix.rn-architecture }}) + config: ./test/perf/metrics-${{ matrix.platform }}.yml + sauce-user: ${{ secrets.SAUCE_USERNAME }} + sauce-key: ${{ secrets.SAUCE_ACCESS_KEY }} react-native-build: name: Build RN ${{ matrix.rn-version }} ${{ matrix.rn-architecture }} ${{ matrix.platform }} ${{ matrix.build-type }} @@ -172,8 +235,8 @@ jobs: strategy: fail-fast: false # keeps matrix running if one fails matrix: - rn-version: ['0.64.4', '0.71.0'] - rn-architecture: ['legacy'] + rn-version: ['0.65.3', '0.71.0'] + rn-architecture: ['legacy', 'new'] platform: ['android', 'ios'] build-type: ['dev', 'production'] include: @@ -182,7 +245,7 @@ jobs: device: 'iPhone 14' # exclude all rn versions lower than 0.70.0 for new architecture exclude: - - rn-version: '0.64.4' + - rn-version: '0.65.3' rn-architecture: 'new' steps: - uses: actions/checkout@v3 @@ -202,13 +265,29 @@ jobs: path: node_modules key: ${{ github.workflow }}-${{ github.job }}-npm-${{ hashFiles('yarn.lock') }} + - name: NPM cache E2E Tests Library + uses: actions/cache@v3 + id: deps-cache-e2e-library + with: + path: test/e2e/node_modules + key: ${{ github.workflow }}-${{ github.job }}-npm-${{ hashFiles('test/e2e/yarn.lock') }} + - name: Install SDK JS Dependencies if: ${{ steps.deps-cache.outputs['cache-hit'] != 'true' }} run: yarn install + - name: Install E2E Tests Library JS Dependencies + if: steps.deps-cache.outputs['deps-cache-e2e-library'] != 'true' + working-directory: test/e2e + run: yarn install + - name: Build SDK run: yarn build + - name: Build E2E Tests Library + working-directory: test/e2e + run: yarn build + - name: Package SDK run: yalc publish @@ -224,6 +303,10 @@ jobs: working-directory: test/react-native/versions/${{ matrix.rn-version }}/RnDiffApp run: yarn install + - name: Add E2E Tests Library to App + working-directory: test/react-native/versions/${{ matrix.rn-version }}/RnDiffApp + run: yarn add ../../../../e2e + - name: Install App Pods if: ${{ matrix.platform == 'ios' }} working-directory: test/react-native/versions/${{ matrix.rn-version }}/RnDiffApp/ios @@ -281,6 +364,157 @@ jobs: -scheme RnDiffApp \ -destination 'platform=iOS Simulator,OS=${{ matrix.runtime }},name=${{ matrix.device }}' \ ONLY_ACTIVE_ARCH=yes \ - -sdk 'iphonesimulator' \ -derivedDataPath "$derivedData" \ build + + - name: Archive Android APK + if: matrix.platform == 'android' && matrix.build-type == 'production' + run: | + BUILD_PATH=test/react-native/versions/${{ matrix.rn-version }}/RnDiffApp/android/app/build/outputs/apk/release + BUILD_NAME=app-release.apk + tar -cvf apk.tar -C $BUILD_PATH $BUILD_NAME + + - name: Archive iOS APP + if: matrix.platform == 'ios' && matrix.build-type == 'production' + run: | + BUILD_PATH=test/react-native/versions/${{ matrix.rn-version }}/RnDiffApp/ios/DerivedData/Build/Products/Release-iphonesimulator + BUILD_NAME=RnDiffApp.app + tar -cvf app.tar -C $BUILD_PATH $BUILD_NAME + + - name: Upload App APK + if: matrix.platform == 'android' && matrix.build-type == 'production' + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.platform }}-${{ matrix.build-type }}-app-package + path: apk.tar + retention-days: 1 + + - name: Upload App APP + if: matrix.platform == 'ios' && matrix.build-type == 'production' + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.platform }}-${{ matrix.build-type }}-app-package + path: app.tar + retention-days: 1 + + react-native-test: + name: Test RN ${{ matrix.rn-version }} ${{ matrix.rn-architecture }} ${{ matrix.platform }} ${{ matrix.build-type }} + needs: react-native-build + runs-on: macos-latest + strategy: + fail-fast: false # keeps matrix running if one fails + matrix: + rn-version: ['0.65.3', '0.71.0'] + rn-architecture: ['legacy', 'new'] + platform: ['android', 'ios'] + build-type: ['production'] + include: + - platform: ios + runtime: 'latest' + device: 'iPhone 14' + # exclude all rn versions lower than 0.70.0 for new architecture + exclude: + - rn-version: '0.65.3' + rn-architecture: 'new' + env: + PLATFORM: ${{ matrix.platform }} + DEVICE: ${{ matrix.device }} + steps: + - uses: actions/checkout@v3 + + - name: Download App Package + if: matrix.build-type == 'production' + uses: actions/download-artifact@v3 + with: + name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.platform }}-${{ matrix.build-type }}-app-package + path: test/e2e + + - name: Extract App Package + working-directory: test/e2e + run: tar -xvf *.tar + + - uses: actions/setup-java@v3 + with: + java-version: '11' + distribution: 'adopt' + + - name: NPM cache E2E Tests Library + uses: actions/cache@v3 + id: deps-cache-e2e-library + with: + path: test/e2e/node_modules + key: ${{ github.workflow }}-${{ github.job }}-npm-${{ hashFiles('test/e2e/yarn.lock') }} + + - name: Install E2E Tests Library JS Dependencies + if: steps.deps-cache.outputs['deps-cache-e2e-library'] != 'true' + working-directory: test/e2e + run: yarn install + + - name: Build iOS WebDriverAgent + if: matrix.platform == 'ios' + working-directory: test/e2e + run: | + mkdir -p "DerivedData" + derivedData="$(cd "DerivedData" ; pwd -P)" + xcodebuild \ + -project node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj \ + -scheme WebDriverAgentRunner \ + GCC_TREAT_WARNINGS_AS_ERRORS=0 \ + COMPILER_INDEX_STORE_ENABLE=NO \ + -destination 'platform=iOS Simulator,OS=${{ matrix.runtime }},name=${{ matrix.device }}' \ + ONLY_ACTIVE_ARCH=yes \ + -derivedDataPath "$derivedData" \ + build + + - name: Start Appium Server + working-directory: test/e2e + run: yarn run appium --log-timestamp --log-no-colors --log appium.${{ matrix.platform }}.log & + + # Wait until the Appium server starts. + - name: Check Appium Server + uses: nick-fields/retry@943e742917ac94714d2f408a0e8320f2d1fcafcd # pin@v2 + with: + timeout_seconds: 60 + max_attempts: 10 + command: curl --output /dev/null --silent --head --fail http://127.0.0.1:4723/sessions + + - name: Run tests on Android + if: ${{ matrix.platform == 'android' }} + env: + APPIUM_APP: ./app-release.apk + uses: reactivecircus/android-emulator-runner@50986b1464923454c95e261820bc626f38490ec0 # pin@v2 + with: + working-directory: test/e2e + api-level: 29 + emulator-options: > + -accel on + -no-snapshot + -gpu swiftshader_indirect + -noaudio + -no-boot-anim + -camera-back none + -camera-front none + -timezone US/Pacific + script: | + # Collect logs + adb logcat '*:D' 2>&1 >adb.log & + adb devices -l + + yarn test --verbose + + - name: Run tests on iOS + if: ${{ matrix.platform == 'ios' }} + working-directory: test/e2e + env: + APPIUM_APP: ./RnDiffApp.app + APPIUM_DERIVED_DATA: DerivedData + run: yarn test --verbose + + - name: Upload logs + if: ${{ always() }} + uses: actions/upload-artifact@v3 + with: + name: ${{ matrix.rn-version }}-${{ matrix.rn-architecture }}-${{ matrix.platform }}-${{ matrix.build-type }}-logs + path: | + test/e2e/*.log + test/e2e/*.png diff --git a/.github/workflows/native-tests.yml b/.github/workflows/native-tests.yml new file mode 100644 index 000000000..de5ef5aaf --- /dev/null +++ b/.github/workflows/native-tests.yml @@ -0,0 +1,49 @@ +name: Native Tests + +on: + push: + branches: [main] + pull_request: + +jobs: + cancel-previous-workflow: + runs-on: ubuntu-latest + steps: + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@b173b6ec0100793626c2d9e6b90435061f4fc3e5 # pin@0.11.0 + with: + access_token: ${{ github.token }} + + test: + name: ios + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + + - name: NPM cache + uses: actions/cache@v3 + id: deps-cache + with: + path: node_modules + key: ${{ github.workflow }}-${{ github.job }}-npm-${{ hashFiles('yarn.lock') }} + + - name: Install SDK JS Dependencies + if: steps.deps-cache.outputs['cache-hit'] != 'true' + run: yarn install + + - name: Install App Pods + working-directory: RNSentryTester + run: pod install + + - name: Run iOS Tests + working-directory: RNSentryTester + env: + SCHEME: RNSentryTester + CONFIGURATION: Release + DESTINATION: 'platform=iOS Simulator,OS=latest,name=iPhone 14' + run: | + env NSUnbufferedIO=YES \ + xcodebuild -workspace *.xcworkspace \ + -scheme $SCHEME -configuration $CONFIGURATION \ + -destination "$DESTINATION" \ + test diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0e7feb018..e45ed0656 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,11 +8,14 @@ on: force: description: Force a release even when there are release-blockers (optional) required: false + merge_target: + description: Target branch to merge into. Uses the default branch as a fallback (optional) + required: false jobs: job_release: runs-on: ubuntu-latest - name: 'Release a new version' + name: "Release a new version" steps: - name: Check out current commit (${{ github.sha }}) uses: actions/checkout@v3 @@ -28,3 +31,4 @@ jobs: with: version: ${{ github.event.inputs.version }} force: ${{ github.event.inputs.force }} + merge_target: ${{ github.event.inputs.merge_target }} diff --git a/.github/workflows/update-deps.yml b/.github/workflows/update-deps.yml index 35a780d16..f2bb6fbba 100644 --- a/.github/workflows/update-deps.yml +++ b/.github/workflows/update-deps.yml @@ -37,26 +37,23 @@ jobs: secrets: api-token: ${{ secrets.CI_DEPLOY_KEY }} - # RN SDK v4 can't be updated to the latest wizard and cli - # This will be returned in v5 - - # wizard: - # uses: getsentry/github-workflows/.github/workflows/updater.yml@v2 - # with: - # path: scripts/update-wizard.sh - # name: Wizard - # pr-strategy: update - # secrets: - # api-token: ${{ secrets.CI_DEPLOY_KEY }} + wizard: + uses: getsentry/github-workflows/.github/workflows/updater.yml@v2 + with: + path: scripts/update-wizard.sh + name: Wizard + pr-strategy: update + secrets: + api-token: ${{ secrets.CI_DEPLOY_KEY }} - # cli: - # uses: getsentry/github-workflows/.github/workflows/updater.yml@v2 - # with: - # path: scripts/update-cli.sh - # name: CLI - # pr-strategy: update - # secrets: - # api-token: ${{ secrets.CI_DEPLOY_KEY }} + cli: + uses: getsentry/github-workflows/.github/workflows/updater.yml@v2 + with: + path: scripts/update-cli.sh + name: CLI + pr-strategy: update + secrets: + api-token: ${{ secrets.CI_DEPLOY_KEY }} sample-rn: uses: getsentry/github-workflows/.github/workflows/updater.yml@v2 diff --git a/.npmignore b/.npmignore index 8dc7daf7b..4acb285cb 100644 --- a/.npmignore +++ b/.npmignore @@ -10,4 +10,5 @@ !react-native.config.js !/ios/**/* !/android/**/* +!src/js/NativeRNSentry.ts !scripts/collect-modules.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 6af90c8ff..0d900712a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,44 @@ # Changelog +## Unreleased + +The React Native SDK version 5 supports both Legacy (from RN 0.65 and above) and New Architecture (from RN 0.69 and above) as well as the new React Native Gradle Plugin (introduced in RN 0.71). For detailed [migration guide visit our docs](https://docs.sentry.io/platforms/react-native/migration/#from-4x-to-5x). + +### Features + +- Add support for the RN New Architecture, backwards compatible RNSentry Turbo Module ([#2522](https://github.com/getsentry/sentry-react-native/pull/2522)) +- Add View Hierarchy to the crashed/errored events ([#2708](https://github.com/getsentry/sentry-react-native/pull/2708)) +- Send react native js engine, turbo module, fabric flags and component stack in Event contexts ([#2552](https://github.com/getsentry/sentry-react-native/pull/2552)) +- Sync `tags`, `extra`, `fingerprint`, `level`, `environment` and `breadcrumbs` from `sentry-cocoa` during event processing. ([#2713](https://github.com/getsentry/sentry-react-native/pull/2713)) + - `breadcrumb.level` value `log` is transformed to `debug` when syncing with native layers. + - Remove `breadcrumb.level` value `critical` transformation to `fatal`. + - Default `breadcrumb.level` is `info` + +### Breaking changes + +- Option `enableAutoPerformanceTracking` renamed to `enableAutoPerformanceTracing` +- Option `enableOutOfMemoryTracking` renamed to `enableWatchdogTerminationTracking` +- Remove link hooks (RN 0.68 and older) ([#2332](https://github.com/getsentry/sentry-react-native/pull/2332)) +- iOS min target 11, Android API min 21, min React Native version 0.65 ([#2522](https://github.com/getsentry/sentry-react-native/pull/2522), [#2687](https://github.com/getsentry/sentry-react-native/pull/2687)) +- New ReactNativeTracingOptions ([#2481](https://github.com/getsentry/sentry-react-native/pull/2481)) + - `idleTimeout` renamed to `idleTimeoutMs` + - `maxTransactionDuration` renamed to `finalTimeoutMs` +- `touchEventBoundaryProps.labelName` property instead of default `accessibilityLabel` fallback ([#2712](https://github.com/getsentry/sentry-react-native/pull/2712)) +- Message event current stack trace moved from `exception` to `threads` ([#2694](https://github.com/getsentry/sentry-react-native/pull/2694)) + +### Fixes + +- Unreachable fallback to fetch transport if native is not available ([#2695](https://github.com/getsentry/sentry-react-native/pull/2695)) + +### Dependencies + +- Bump Cocoa SDK from v7.31.5 to v8.0.0 ([#2756](https://github.com/getsentry/sentry-react-native/pull/2756)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#800) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/7.31.5...8.0.0) +- Bump CLI from v1.74.4 to v2.10.0 ([#2669](https://github.com/getsentry/sentry-react-native/pull/2669)) + - [changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#2100) + - [diff](https://github.com/getsentry/sentry-cli/compare/1.74.4...2.10.0) + ## 4.15.0 ### Features @@ -22,6 +61,56 @@ - [changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md#7372) - [diff](https://github.com/getsentry/sentry-javascript/compare/7.32.1...7.37.2) +## 5.0.0-rc.1 + +### Fixes + +- React Native Error Handlers Integration doesn't crash if ErrorUtils are not available ([#2808](https://github.com/getsentry/sentry-react-native/pull/2808)) + +## 5.0.0-beta.2 + +### Features + +- Add View Hierarchy to the crashed/errored events ([#2708](https://github.com/getsentry/sentry-react-native/pull/2708)) +- Collect modules script for XCode builds supports NODE_BINARY to set path to node executable ([#2805](https://github.com/getsentry/sentry-react-native/pull/2805)) + +### Dependencies + +- Bump Android SDK from v6.12.1 to v6.14.0 ([#2790](https://github.com/getsentry/sentry-react-native/pull/2790), [#2809](https://github.com/getsentry/sentry-react-native/pull/2809), [#2828](https://github.com/getsentry/sentry-react-native/pull/2828)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#6140) + - [diff](https://github.com/getsentry/sentry-java/compare/6.12.1...6.14.0) +- Bump Sample React Native from v0.71.0 to v0.71.1 ([#2767](https://github.com/getsentry/sentry-react-native/pull/2767)) + - [changelog](https://github.com/facebook/react-native/blob/main/CHANGELOG.md#v0711) + - [diff](https://github.com/facebook/react-native/compare/v0.71.0...v0.71.1) +- Bump JavaScript SDK from v7.32.1 to v7.37.2 ([#2785](https://github.com/getsentry/sentry-react-native/pull/2785), [#2799](https://github.com/getsentry/sentry-react-native/pull/2799), [#2818](https://github.com/getsentry/sentry-react-native/pull/2818)) + - [changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md#7372) + - [diff](https://github.com/getsentry/sentry-javascript/compare/7.32.1...7.37.2) + +## 5.0.0-beta.1 + +- Latest changes from 4.14.0 + +### Breaking changes + +- Option `enableAutoPerformanceTracking` renamed to `enableAutoPerformanceTracing` +- Option `enableOutOfMemoryTracking` renamed to `enableWatchdogTerminationTracking` + +### Features + +- Sync `tags`, `extra`, `fingerprint`, `level`, `environment` and `breadcrumbs` from `sentry-cocoa` during event processing. ([#2713](https://github.com/getsentry/sentry-react-native/pull/2713)) + - `breadcrumb.level` value `log` is transformed to `debug` when syncing with native layers. + - Remove `breadcrumb.level` value `critical` transformation to `fatal`. + - Default `breadcrumb.level` is `info` + +### Dependencies + +- Bump Cocoa SDK from v7.31.5 to v8.0.0 ([#2756](https://github.com/getsentry/sentry-react-native/pull/2756)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/main/CHANGELOG.md#800) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/7.31.5...8.0.0) +- Bump Android SDK from v6.12.1 to v6.13.0 ([#2790](https://github.com/getsentry/sentry-react-native/pull/2790)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#6130) + - [diff](https://github.com/getsentry/sentry-java/compare/6.12.1...6.13.0) + ## 4.14.0 ### Features @@ -41,6 +130,19 @@ - [changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md#7321) - [diff](https://github.com/getsentry/sentry-javascript/compare/7.29.0...7.32.1) +## 5.0.0-alpha.11 + +- Latest changes from 4.13.0 + +### Breaking changes + +- Message event current stack trace moved from exception to threads ([#2694](https://github.com/getsentry/sentry-react-native/pull/2694)) +- `touchEventBoundaryProps.labelName` property instead of default `accessibilityLabel` fallback ([#2712](https://github.com/getsentry/sentry-react-native/pull/2712)) + +### Fixes + +- Unreachable fallback to fetch transport if native is not available ([#2695](https://github.com/getsentry/sentry-react-native/pull/2695)) + ## 4.13.0 ### Fixes @@ -82,6 +184,16 @@ - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#692) - [diff](https://github.com/getsentry/sentry-java/compare/6.9.1...6.9.2) +## 5.0.0-alpha.10 + +- Latest changes from 4.11.0 + +### Dependencies + +- Bump CLI from v1.74.4 to v2.10.0 ([#2669](https://github.com/getsentry/sentry-react-native/pull/2669)) + - [changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#2100) + - [diff](https://github.com/getsentry/sentry-cli/compare/1.74.4...2.10.0) + ## 4.11.0 ### Features @@ -105,6 +217,14 @@ - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#691) - [diff](https://github.com/getsentry/sentry-java/compare/6.8.0...6.9.1) +## 5.0.0-alpha.9 + +- Latest changes from 4.10.0 + +### Fixes + +- Add missing source Spec for RNSentry Codegen. ([#2639](https://github.com/getsentry/sentry-react-native/pull/2639)) + ## 4.10.0 ### Features @@ -118,6 +238,10 @@ - [changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md#7211) - [diff](https://github.com/getsentry/sentry-javascript/compare/7.20.1...7.21.1) +## 5.0.0-alpha.8 + +- Latest changes from 4.9.0 + ## 4.9.0 ### Features @@ -156,6 +280,30 @@ - [changelog](https://github.com/getsentry/sentry-cocoa/blob/master/CHANGELOG.md#7290) - [diff](https://github.com/getsentry/sentry-cocoa/compare/7.28.0...7.29.0) +## 5.0.0-alpha.7 + +- Latest changes from 4.7.1 + +### Fixes + +- Remove hardcoded Folly version ([#2558](https://github.com/getsentry/sentry-react-native/pull/2558)) + +### Features + +- Send react native js engine, turbo module, fabric flags and component stack in Event contexts ([#2552](https://github.com/getsentry/sentry-react-native/pull/2552)) + +### Dependencies + +- Bump CLI from v1.74.4 to v2.7.0 ([#2457](https://github.com/getsentry/sentry-react-native/pull/2457)) + - [changelog](https://github.com/getsentry/sentry-cli/blob/master/CHANGELOG.md#270) + - [diff](https://github.com/getsentry/sentry-cli/compare/1.74.4...2.7.0) +- Bump Android SDK from v6.5.0 to v6.6.0 ([#2572](https://github.com/getsentry/sentry-react-native/pull/2572)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#660) + - [diff](https://github.com/getsentry/sentry-java/compare/6.5.0...6.6.0) +- Bump Cocoa SDK from v7.28.0 to v7.29.0 ([#2571](https://github.com/getsentry/sentry-react-native/pull/2571)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/master/CHANGELOG.md#7290) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/7.28.0...7.29.0) + ## 4.7.1 ### Fixes @@ -177,6 +325,28 @@ - [changelog](https://github.com/getsentry/sentry-cocoa/blob/master/CHANGELOG.md#7280) - [diff](https://github.com/getsentry/sentry-cocoa/compare/7.27.1...7.28.0) +## 5.0.0-alpha.6 + +- Latest changes from 4.6.1 + +### Features + +- Add initial support for the RN New Architecture, backwards compatible RNSentry Turbo Module ([#2522](https://github.com/getsentry/sentry-react-native/pull/2522)) + +### Breaking changes + +- New ReactNativeTracingOptions idleTimeoutMs and finalTimeoutMs replacing idleTimeout and maxTransactionDuration respectively ([#2481](https://github.com/getsentry/sentry-react-native/pull/2481)) +- iOS min target 12.4, Android API min 21, min React Native version 0.70 ([#2522](https://github.com/getsentry/sentry-react-native/pull/2522)) + +### Dependencies + +- Bump Android SDK from v6.4.3 to v6.5.0 ([#2535](https://github.com/getsentry/sentry-react-native/pull/2535)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#650) + - [diff](https://github.com/getsentry/sentry-java/compare/6.4.3...6.5.0) +- Bump JavaScript SDK from v7.14.2 to v7.15.0 ([#2536](https://github.com/getsentry/sentry-react-native/pull/2536)) + - [changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md#7150) + - [diff](https://github.com/getsentry/sentry-javascript/compare/7.14.2...7.15.0) + ## 4.6.1 ### Fixes @@ -197,6 +367,24 @@ - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#643) - [diff](https://github.com/getsentry/sentry-java/compare/6.4.2...6.4.3) +## 5.0.0-alpha.5 + +### Fixes + +- Make `configureScope` callback safe [#2510](https://github.com/getsentry/sentry-react-native/pull/2510) + +### Dependencies + +- Bump JavaScript SDK from v7.14.0 to v7.14.1 ([#2511](https://github.com/getsentry/sentry-react-native/pull/2511)) + - [changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md#7141) + - [diff](https://github.com/getsentry/sentry-javascript/compare/7.14.0...7.14.1) +- Bump Cocoa SDK from v7.27.0 to v7.27.1 ([#2521](https://github.com/getsentry/sentry-react-native/pull/2521)) + - [changelog](https://github.com/getsentry/sentry-cocoa/blob/master/CHANGELOG.md#7271) + - [diff](https://github.com/getsentry/sentry-cocoa/compare/7.27.0...7.27.1) +- Bump Android SDK from v6.4.2 to v6.4.3 ([#2520](https://github.com/getsentry/sentry-react-native/pull/2520)) + - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#643) + - [diff](https://github.com/getsentry/sentry-java/compare/6.4.2...6.4.3) + ## 4.6.0 ### Fixes @@ -221,6 +409,14 @@ - [changelog](https://github.com/getsentry/sentry-javascript/blob/master/CHANGELOG.md#7140) - [diff](https://github.com/getsentry/sentry-javascript/compare/7.13.0...7.14.0) +## 5.0.0-alpha.4 + +- Latest changes from 4.5.0 + +### Breaking changes + +- New ReactNativeTracingOptions idleTimeoutMs and finalTimeoutMs replacing idleTimeout and maxTransactionDuration respectively ([#2481](https://github.com/getsentry/sentry-react-native/pull/2481)) + ## 4.5.0 ### Features @@ -261,6 +457,16 @@ - [changelog](https://github.com/getsentry/sentry-cocoa/blob/master/CHANGELOG.md#7251) - [diff](https://github.com/getsentry/sentry-cocoa/compare/7.24.1...7.25.1) +## 5.0.0-alpha.3 + +- Latest changes from 4.3.x + +### Dependencies + +- Bump Wizard from v2.0.0 to v2.2.0 ([#2460](https://github.com/getsentry/sentry-react-native/pull/2460)) + - [changelog](https://github.com/getsentry/sentry-wizard/blob/master/CHANGELOG.md#v220) + - [diff](https://github.com/getsentry/sentry-wizard/compare/v2.0.0...v2.2.0) + ## 4.3.0 ### Features @@ -285,6 +491,16 @@ - ReactNativeTracing wrongly marks transactions as deadline_exceeded when it reaches the idleTimeout ([#2427](https://github.com/getsentry/sentry-react-native/pull/2427)) +## 5.0.0-alpha.2 + +- Latest changes from 4.2.x + +## 5.0.0-alpha.1 + +### Fixes + +- Auto linking for RN >= 0.69 ([#2332](https://github.com/getsentry/sentry-react-native/pull/2332)) + ## 4.2.3 ### Fixes @@ -1008,10 +1224,10 @@ This release is a breaking change an code changes are necessary. New way to import and init the SDK: ```js -import * as Sentry from "@sentry/react-native"; +import * as Sentry from '@sentry/react-native'; Sentry.init({ - dsn: "DSN", + dsn: 'DSN', }); ``` @@ -1246,7 +1462,7 @@ We decided to deactivate stack trace merging by default on iOS since it seems to To activate it set: ```js -Sentry.config("___DSN___", { +Sentry.config('___DSN___', { deactivateStacktraceMerging: false, }); ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c43a9e089..caa7dee22 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,15 +42,42 @@ yarn test:watch Now we can go into the sample project, install and build it: ```sh -cd sample/ +cd sample-new-architecture/ yarn +``` + +### Run the emulators (legacy-architecture): + +For android switch `newArchEnabled` to `false` in [android/gradle.properties](https://github.com/getsentry/sentry-react-native/blob/c95aa21497ca93aaaaf0b44d170dc39dc7bcf660/sample-new-architecture/android/gradle.properties#L40). For iOS explicitly disable fabric in `sample-new-architecture/ios/Podfile` by setting `:fabric_enabled => false` before `pod install`. + +```sh +yarn pod-install-legacy +yarn run-ios + +yarn run-android + +# Release builds +yarn pod-install-legacy-production +yarn run-ios --configuration Release + +yarn run-android --variant=release +``` + +### Run the emulators (new-architecture): +```sh +yarn pod-install +yarn run-ios + +yarn run-android + +# Release builds +yarn pod-install-production +yarn run-ios --configuration Release -# Build iOS -cd ios -pod install -cd .. +yarn run-android --variant=release ``` +### Optional You can optionally start the Metro bundler if you want to control where it runs: ```sh diff --git a/README.md b/README.md index 6f1b1e8d2..864055fe2 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he ## Requirements -- `react-native >= 0.56.0` +- `react-native >= 0.65.0` ## Features @@ -34,6 +34,7 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he - RAM bundle support - Hermes support - Expo support ([sentry-expo](https://github.com/expo/sentry-expo)) +- RN New Architecture support ## Installation and Usage @@ -43,14 +44,10 @@ To install the package: npm install --save @sentry/react-native # OR yarn add @sentry/react-native -``` - -If you are using a version of React Native <= 0.60.x link the package using `react-native`. -```sh -react-native link @sentry/react-native -# OR, if self hosting -SENTRY_WIZARD_URL=http://sentry.acme.com/ react-native link @sentry/react-native +# AND +npx @sentry/wizard -i reactNative -p ios android +npx pod-install ``` How to use it: diff --git a/RNSentry.podspec b/RNSentry.podspec index 177290246..649aaebe3 100644 --- a/RNSentry.podspec +++ b/RNSentry.podspec @@ -1,6 +1,8 @@ require 'json' version = JSON.parse(File.read('package.json'))["version"] +folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' + Pod::Spec.new do |s| s.name = 'RNSentry' s.version = version @@ -10,15 +12,30 @@ Pod::Spec.new do |s| s.homepage = "https://github.com/getsentry/sentry-react-native" s.source = { :git => 'https://github.com/getsentry/sentry-react-native.git', :tag => "#{s.version}"} - s.ios.deployment_target = "8.0" - s.osx.deployment_target = "10.10" - s.tvos.deployment_target = "9.0" + s.ios.deployment_target = "11.0" + s.osx.deployment_target = "10.13" + s.tvos.deployment_target = "11.0" s.preserve_paths = '*.js' s.dependency 'React-Core' - s.dependency 'Sentry/HybridSDK', '7.31.5' + s.dependency 'Sentry/HybridSDK', '8.0.0' - s.source_files = 'ios/RNSentry.{h,m}' + s.source_files = 'ios/**/*.{h,mm}' s.public_header_files = 'ios/RNSentry.h' + + # This guard prevent to install the dependencies when we run `pod install` in the old architecture. + if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then + s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" + s.pod_target_xcconfig = { + "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" + } + + s.dependency "React-Codegen" + s.dependency "RCT-Folly" + s.dependency "RCTRequired" + s.dependency "RCTTypeSafety" + s.dependency "ReactCommon/turbomodule/core" + end end diff --git a/RNSentryTester/Podfile b/RNSentryTester/Podfile new file mode 100644 index 000000000..d87e1cefa --- /dev/null +++ b/RNSentryTester/Podfile @@ -0,0 +1,8 @@ +require_relative '../node_modules/react-native/scripts/react_native_pods' + +platform :ios, '12.4' + +target 'RNSentryTesterTests' do + use_react_native!() + pod 'RNSentry', :path => '../RNSentry.podspec' +end diff --git a/RNSentryTester/RNSentryTester.xcodeproj/project.pbxproj b/RNSentryTester/RNSentryTester.xcodeproj/project.pbxproj new file mode 100644 index 000000000..71c6badb9 --- /dev/null +++ b/RNSentryTester/RNSentryTester.xcodeproj/project.pbxproj @@ -0,0 +1,374 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 56; + objects = { + +/* Begin PBXBuildFile section */ + 33F58AD02977037D008F60EA /* RNSentry+initNativeSdk.mm in Sources */ = {isa = PBXBuildFile; fileRef = 33F58ACF2977037D008F60EA /* RNSentry+initNativeSdk.mm */; }; + B5859A50A3E865EF5E61465A /* libPods-RNSentryTesterTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 650CB718ACFBD05609BF2126 /* libPods-RNSentryTesterTests.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1482D5685A340AB93348A43D /* Pods-RNSentryTesterTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNSentryTesterTests.release.xcconfig"; path = "Target Support Files/Pods-RNSentryTesterTests/Pods-RNSentryTesterTests.release.xcconfig"; sourceTree = ""; }; + 3360898D29524164007C7730 /* RNSentryTesterTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RNSentryTesterTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 33F58ACF2977037D008F60EA /* RNSentry+initNativeSdk.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "RNSentry+initNativeSdk.mm"; sourceTree = ""; }; + 650CB718ACFBD05609BF2126 /* libPods-RNSentryTesterTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RNSentryTesterTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + E2321E7CFA55AB617247098E /* Pods-RNSentryTesterTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RNSentryTesterTests.debug.xcconfig"; path = "Target Support Files/Pods-RNSentryTesterTests/Pods-RNSentryTesterTests.debug.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + BB7D14838753E6599863899B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B5859A50A3E865EF5E61465A /* libPods-RNSentryTesterTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00D0AE33FB669AAC85D66F8D /* Pods */ = { + isa = PBXGroup; + children = ( + E2321E7CFA55AB617247098E /* Pods-RNSentryTesterTests.debug.xcconfig */, + 1482D5685A340AB93348A43D /* Pods-RNSentryTesterTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + 3360896929524163007C7730 = { + isa = PBXGroup; + children = ( + 3360899029524164007C7730 /* RNSentryTesterTests */, + 3360897329524163007C7730 /* Products */, + 00D0AE33FB669AAC85D66F8D /* Pods */, + E9CBAA4D06145A9DB2C82C1B /* Frameworks */, + ); + sourceTree = ""; + }; + 3360897329524163007C7730 /* Products */ = { + isa = PBXGroup; + children = ( + 3360898D29524164007C7730 /* RNSentryTesterTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 3360899029524164007C7730 /* RNSentryTesterTests */ = { + isa = PBXGroup; + children = ( + 33F58ACF2977037D008F60EA /* RNSentry+initNativeSdk.mm */, + ); + path = RNSentryTesterTests; + sourceTree = ""; + }; + E9CBAA4D06145A9DB2C82C1B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 650CB718ACFBD05609BF2126 /* libPods-RNSentryTesterTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 3360898C29524164007C7730 /* RNSentryTesterTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 336089A429524164007C7730 /* Build configuration list for PBXNativeTarget "RNSentryTesterTests" */; + buildPhases = ( + 30F19D4E16BEEFEC68733838 /* [CP] Check Pods Manifest.lock */, + 3360898929524164007C7730 /* Sources */, + BB7D14838753E6599863899B /* Frameworks */, + E56C5E3822DFF9C2796CEB4A /* [CP] Embed Pods Frameworks */, + CC7959F3721CB3AD7CB6A047 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = RNSentryTesterTests; + productName = RNSentryTesterTests; + productReference = 3360898D29524164007C7730 /* RNSentryTesterTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 3360896A29524163007C7730 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1420; + TargetAttributes = { + 3360898C29524164007C7730 = { + CreatedOnToolsVersion = 14.2; + }; + }; + }; + buildConfigurationList = 3360896D29524163007C7730 /* Build configuration list for PBXProject "RNSentryTester" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 3360896929524163007C7730; + productRefGroup = 3360897329524163007C7730 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 3360898C29524164007C7730 /* RNSentryTesterTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 30F19D4E16BEEFEC68733838 /* [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-RNSentryTesterTests-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; + }; + CC7959F3721CB3AD7CB6A047 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNSentryTesterTests/Pods-RNSentryTesterTests-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNSentryTesterTests/Pods-RNSentryTesterTests-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNSentryTesterTests/Pods-RNSentryTesterTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + E56C5E3822DFF9C2796CEB4A /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNSentryTesterTests/Pods-RNSentryTesterTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-RNSentryTesterTests/Pods-RNSentryTesterTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RNSentryTesterTests/Pods-RNSentryTesterTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 3360898929524164007C7730 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33F58AD02977037D008F60EA /* RNSentry+initNativeSdk.mm in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 3360899F29524164007C7730 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 336089A029524164007C7730 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 336089A529524164007C7730 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = E2321E7CFA55AB617247098E /* Pods-RNSentryTesterTests.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.RNSentryTesterTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = NO; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Debug; + }; + 336089A629524164007C7730 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 1482D5685A340AB93348A43D /* Pods-RNSentryTesterTests.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.RNSentryTesterTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = NO; + SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; + SWIFT_EMIT_LOC_STRINGS = NO; + TARGETED_DEVICE_FAMILY = 1; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 3360896D29524163007C7730 /* Build configuration list for PBXProject "RNSentryTester" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3360899F29524164007C7730 /* Debug */, + 336089A029524164007C7730 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 336089A429524164007C7730 /* Build configuration list for PBXNativeTarget "RNSentryTesterTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 336089A529524164007C7730 /* Debug */, + 336089A629524164007C7730 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 3360896A29524163007C7730 /* Project object */; +} diff --git a/ios/RNSentry.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/RNSentryTester/RNSentryTester.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from ios/RNSentry.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to RNSentryTester/RNSentryTester.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/ios/RNSentry.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/RNSentryTester/RNSentryTester.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from ios/RNSentry.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to RNSentryTester/RNSentryTester.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/RNSentryTester/RNSentryTester.xcodeproj/xcshareddata/xcschemes/RNSentryTester.xcscheme b/RNSentryTester/RNSentryTester.xcodeproj/xcshareddata/xcschemes/RNSentryTester.xcscheme new file mode 100644 index 000000000..b0388fffe --- /dev/null +++ b/RNSentryTester/RNSentryTester.xcodeproj/xcshareddata/xcschemes/RNSentryTester.xcscheme @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RNSentryTester/RNSentryTester.xcworkspace/contents.xcworkspacedata b/RNSentryTester/RNSentryTester.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..020faef6c --- /dev/null +++ b/RNSentryTester/RNSentryTester.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/RNSentryTester/RNSentryTester.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/RNSentryTester/RNSentryTester.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/RNSentryTester/RNSentryTester.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/RNSentryTester/RNSentryTesterTests/RNSentry+initNativeSdk.mm b/RNSentryTester/RNSentryTesterTests/RNSentry+initNativeSdk.mm new file mode 100644 index 000000000..4c7b912f8 --- /dev/null +++ b/RNSentryTester/RNSentryTesterTests/RNSentry+initNativeSdk.mm @@ -0,0 +1,47 @@ +#import +#import +#import +#import "RNSentry.h" + +@interface RNSentryInitNativeSdkTests : XCTestCase + +@end + +@implementation RNSentryInitNativeSdkTests + +- (void)testCreateOptionsWithDictionaryRemovesPerformanceProperties +{ + RNSentry * rnSentry = [[RNSentry alloc] init]; + NSError* error = nil; + + NSDictionary *_Nonnull mockedReactNativeDictionary = @{ + @"dsn": @"https://abcd@efgh.ingest.sentry.io/123456", + @"beforeSend": @"will_be_overwritten", + @"enableNativeCrashHandling": @YES, + + }; + SentryOptions* actualOptions = [rnSentry createOptionsWithDictionary:mockedReactNativeDictionary error:&error]; + + XCTAssertNotNil(actualOptions, @"Did not create sentry options"); + XCTAssertNil(error, @"Should not pass no error"); + XCTAssertNotNil(actualOptions.beforeSend, @"Before send is overwriten by the native RNSentry implementation"); + XCTAssertEqual(actualOptions.tracesSampleRate, nil, @"Traces sample rate should not be passed to native"); + XCTAssertEqual(actualOptions.tracesSampler, nil, @"Traces sampler should not be passed to native"); +} + + +- (void)testPassesErrorOnWrongDsn +{ + RNSentry * rnSentry = [[RNSentry alloc] init]; + NSError* error = nil; + + NSDictionary *_Nonnull mockedReactNativeDictionary = @{ + @"dsn": @"not_a_valid_dsn" + }; + SentryOptions* actualOptions = [rnSentry createOptionsWithDictionary:mockedReactNativeDictionary error:&error]; + + XCTAssertNil(actualOptions, @"Created invalid sentry options"); + XCTAssertNotNil(error, @"Did not created error on invalid dsn"); +} + +@end diff --git a/android/build.gradle b/android/build.gradle index 396300232..cf16c7315 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -2,13 +2,20 @@ def safeExtGet(prop, fallback) { rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback } +def isNewArchitectureEnabled() { + return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" +} + apply plugin: 'com.android.library' +if (isNewArchitectureEnabled()) { + apply plugin: 'com.facebook.react' +} android { compileSdkVersion safeExtGet('compileSdkVersion', 31) defaultConfig { - minSdkVersion safeExtGet('minSdkVersion', 16) + minSdkVersion safeExtGet('minSdkVersion', 21) targetSdkVersion safeExtGet('targetSdkVersion', 31) versionCode 1 versionName "1.0" @@ -19,6 +26,17 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + } + + sourceSets { + main { + if (isNewArchitectureEnabled()) { + java.srcDirs += ['src/newarch'] + } else { + java.srcDirs += ['src/oldarch'] + } + } } } diff --git a/android/src/main/java/io/sentry/react/RNSentryModule.java b/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java similarity index 91% rename from android/src/main/java/io/sentry/react/RNSentryModule.java rename to android/src/main/java/io/sentry/react/RNSentryModuleImpl.java index 168d85794..f96c83967 100644 --- a/android/src/main/java/io/sentry/react/RNSentryModule.java +++ b/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java @@ -9,13 +9,12 @@ import android.content.res.AssetManager; import android.util.SparseIntArray; +import androidx.annotation.Nullable; import androidx.core.app.FrameMetricsAggregator; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMapKeySetIterator; @@ -24,7 +23,6 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; -import com.facebook.react.module.annotations.ReactModule; import java.io.BufferedInputStream; import java.io.File; @@ -43,6 +41,7 @@ import io.sentry.DateUtils; import io.sentry.HubAdapter; import io.sentry.ILogger; +import io.sentry.ISerializer; import io.sentry.Integration; import io.sentry.Sentry; import io.sentry.SentryDate; @@ -55,15 +54,16 @@ import io.sentry.android.core.BuildInfoProvider; import io.sentry.android.core.CurrentActivityHolder; import io.sentry.android.core.NdkIntegration; -import io.sentry.android.core.ScreenshotEventProcessor; import io.sentry.android.core.SentryAndroid; +import io.sentry.android.core.ViewHierarchyEventProcessor; import io.sentry.protocol.SdkVersion; import io.sentry.protocol.SentryException; import io.sentry.protocol.SentryPackage; import io.sentry.protocol.User; +import io.sentry.protocol.ViewHierarchy; +import io.sentry.util.JsonSerializationUtils; -@ReactModule(name = RNSentryModule.NAME) -public class RNSentryModule extends ReactContextBaseJavaModule { +public class RNSentryModuleImpl { public static final String NAME = "RNSentry"; @@ -72,10 +72,10 @@ public class RNSentryModule extends ReactContextBaseJavaModule { private static final String modulesPath = "modules.json"; private static final Charset UTF_8 = Charset.forName("UTF-8"); + private final ReactApplicationContext reactApplicationContext; private final PackageInfo packageInfo; private FrameMetricsAggregator frameMetricsAggregator = null; private boolean androidXAvailable; - private ScreenshotEventProcessor screenshotEventProcessor; private static boolean didFetchAppStart; @@ -86,18 +86,20 @@ public class RNSentryModule extends ReactContextBaseJavaModule { private static final int SCREENSHOT_TIMEOUT_SECONDS = 2; - public RNSentryModule(ReactApplicationContext reactContext) { - super(reactContext); - packageInfo = getPackageInfo(reactContext); + public RNSentryModuleImpl(ReactApplicationContext reactApplicationContext) { + packageInfo = getPackageInfo(reactApplicationContext); + this.reactApplicationContext = reactApplicationContext; } - @Override - public String getName() { - return NAME; + private ReactApplicationContext getReactApplicationContext() { + return this.reactApplicationContext; } + private @Nullable + Activity getCurrentActivity() { + return this.reactApplicationContext.getCurrentActivity(); + } - @ReactMethod public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { SentryAndroid.init(this.getReactApplicationContext(), options -> { if (rnOptions.hasKey("debug") && rnOptions.getBoolean("debug")) { @@ -152,6 +154,9 @@ public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { if (rnOptions.hasKey("attachScreenshot")) { options.setAttachScreenshot(rnOptions.getBoolean("attachScreenshot")); } + if (rnOptions.hasKey("attachViewHierarchy")) { + options.setAttachViewHierarchy(rnOptions.getBoolean("attachViewHierarchy")); + } if (rnOptions.hasKey("sendDefaultPii")) { options.setSendDefaultPii(rnOptions.getBoolean("sendDefaultPii")); } @@ -199,21 +204,19 @@ public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { promise.resolve(true); } - @ReactMethod public void crash() { throw new RuntimeException("TEST - Sentry Client Crash (only works in release mode)"); } - @ReactMethod public void fetchModules(Promise promise) { final AssetManager assets = this.getReactApplicationContext().getResources().getAssets(); try (final InputStream stream = - new BufferedInputStream(assets.open(RNSentryModule.modulesPath))) { + new BufferedInputStream(assets.open(RNSentryModuleImpl.modulesPath))) { int size = stream.available(); byte[] buffer = new byte[size]; stream.read(buffer); stream.close(); - String modulesJson = new String(buffer, RNSentryModule.UTF_8); + String modulesJson = new String(buffer, RNSentryModuleImpl.UTF_8); promise.resolve(modulesJson); } catch (FileNotFoundException e) { promise.resolve(null); @@ -223,7 +226,6 @@ public void fetchModules(Promise promise) { } } - @ReactMethod public void fetchNativeRelease(Promise promise) { WritableMap release = Arguments.createMap(); release.putString("id", packageInfo.packageName); @@ -232,7 +234,6 @@ public void fetchNativeRelease(Promise promise) { promise.resolve(release); } - @ReactMethod public void fetchNativeAppStart(Promise promise) { final AppStartState appStartInstance = AppStartState.getInstance(); final SentryDate appStartTime = appStartInstance.getAppStartTime(); @@ -264,7 +265,6 @@ public void fetchNativeAppStart(Promise promise) { /** * Returns frames metrics at the current point in time. */ - @ReactMethod public void fetchNativeFrames(Promise promise) { if (!isFrameMetricsAggregatorAvailable()) { promise.resolve(null); @@ -314,7 +314,6 @@ public void fetchNativeFrames(Promise promise) { } } - @ReactMethod public void captureEnvelope(ReadableArray rawBytes, ReadableMap options, Promise promise) { byte[] bytes = new byte[rawBytes.size()]; for (int i = 0; i < rawBytes.size(); i++) { @@ -339,7 +338,6 @@ public void captureEnvelope(ReadableArray rawBytes, ReadableMap options, Promise promise.resolve(true); } - @ReactMethod public void captureScreenshot(Promise promise) { final Activity activity = getCurrentActivity(); @@ -395,6 +393,35 @@ private static byte[] takeScreenshotOnUiThread(Activity activity) { return bytesWrapper[0]; } + public void fetchViewHierarchy(Promise promise) { + final @Nullable Activity activity = getCurrentActivity(); + final @Nullable ViewHierarchy viewHierarchy = ViewHierarchyEventProcessor.snapshotViewHierarchy(activity, logger); + if (viewHierarchy == null) { + logger.log(SentryLevel.ERROR, "Could not get ViewHierarchy."); + promise.resolve(null); + return; + } + + ISerializer serializer = HubAdapter.getInstance().getOptions().getSerializer(); + final @Nullable byte[] bytes = JsonSerializationUtils.bytesFrom(serializer, logger, viewHierarchy); + if (bytes == null) { + logger.log(SentryLevel.ERROR, "Could not serialize ViewHierarchy."); + promise.resolve(null); + return; + } + if (bytes.length < 1) { + logger.log(SentryLevel.ERROR, "Got empty bytes array after serializing ViewHierarchy."); + promise.resolve(null); + return; + } + + final WritableNativeArray data = new WritableNativeArray(); + for (final byte b : bytes) { + data.pushInt(b); + } + promise.resolve(data); + } + private static PackageInfo getPackageInfo(Context ctx) { try { return ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0); @@ -404,7 +431,6 @@ private static PackageInfo getPackageInfo(Context ctx) { } } - @ReactMethod public void setUser(final ReadableMap userKeys, final ReadableMap userDataKeys) { Sentry.configureScope(scope -> { if (userKeys == null && userDataKeys == null) { @@ -455,7 +481,6 @@ public void setUser(final ReadableMap userKeys, final ReadableMap userDataKeys) }); } - @ReactMethod public void addBreadcrumb(final ReadableMap breadcrumb) { Sentry.configureScope(scope -> { Breadcrumb breadcrumbInstance = new Breadcrumb(); @@ -495,7 +520,7 @@ public void addBreadcrumb(final ReadableMap breadcrumb) { if (breadcrumb.hasKey("data")) { final ReadableMap data = breadcrumb.getMap("data"); - for(final Map.Entry entry : data.toHashMap().entrySet()) { + for (final Map.Entry entry : data.toHashMap().entrySet()) { final Object value = entry.getValue(); // data is ConcurrentHashMap and can't have null values if (value != null) { @@ -508,21 +533,18 @@ public void addBreadcrumb(final ReadableMap breadcrumb) { }); } - @ReactMethod public void clearBreadcrumbs() { Sentry.configureScope(scope -> { scope.clearBreadcrumbs(); }); } - @ReactMethod public void setExtra(String key, String extra) { Sentry.configureScope(scope -> { scope.setExtra(key, extra); }); } - @ReactMethod public void setContext(final String key, final ReadableMap context) { if (key == null || context == null) { return; @@ -534,14 +556,12 @@ public void setContext(final String key, final ReadableMap context) { }); } - @ReactMethod public void setTag(String key, String value) { Sentry.configureScope(scope -> { scope.setTag(key, value); }); } - @ReactMethod public void closeNativeSdk(Promise promise) { Sentry.close(); @@ -550,7 +570,6 @@ public void closeNativeSdk(Promise promise) { promise.resolve(true); } - @ReactMethod public void enableNativeFramesTracking() { androidXAvailable = checkAndroidXAvailability(); @@ -576,7 +595,6 @@ public void enableNativeFramesTracking() { } } - @ReactMethod public void disableNativeFramesTracking() { if (isFrameMetricsAggregatorAvailable()) { frameMetricsAggregator.stop(); diff --git a/android/src/main/java/io/sentry/react/RNSentryPackage.java b/android/src/main/java/io/sentry/react/RNSentryPackage.java index 06cb39406..eb2fd90f2 100644 --- a/android/src/main/java/io/sentry/react/RNSentryPackage.java +++ b/android/src/main/java/io/sentry/react/RNSentryPackage.java @@ -1,30 +1,46 @@ package io.sentry.react; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import androidx.annotation.Nullable; + +import java.util.HashMap; +import java.util.Map; -import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; -import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.module.model.ReactModuleInfoProvider; +import com.facebook.react.TurboReactPackage; -public class RNSentryPackage implements ReactPackage { - public RNSentryPackage() { - } +public class RNSentryPackage extends TurboReactPackage { - @Override - public List createNativeModules(ReactApplicationContext reactContext) { - return Arrays.asList(new RNSentryModule(reactContext)); + @Nullable + @Override + public NativeModule getModule(String name, ReactApplicationContext reactContext) { + if (name.equals(RNSentryModuleImpl.NAME)) { + return new RNSentryModule(reactContext); + } else { + return null; } + } - public List> createJSModules() { - return Collections.emptyList(); - } + @Override + public ReactModuleInfoProvider getReactModuleInfoProvider() { + return () -> { + final Map moduleInfos = new HashMap<>(); + boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + moduleInfos.put( + RNSentryModuleImpl.NAME, + new ReactModuleInfo( + RNSentryModuleImpl.NAME, + RNSentryModuleImpl.NAME, + false, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + isTurboModule // isTurboModule + )); + return moduleInfos; + }; + } - @Override - public List createViewManagers(ReactApplicationContext reactContext) { - return Collections.emptyList(); - } } diff --git a/android/src/newarch/java/io/sentry/react/RNSentryModule.java b/android/src/newarch/java/io/sentry/react/RNSentryModule.java new file mode 100644 index 000000000..40eb787b1 --- /dev/null +++ b/android/src/newarch/java/io/sentry/react/RNSentryModule.java @@ -0,0 +1,124 @@ +package io.sentry.react; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.Promise; + +public class RNSentryModule extends NativeRNSentrySpec { + + private final RNSentryModuleImpl impl; + + RNSentryModule(ReactApplicationContext reactContext) { + super(reactContext); + this.impl = new RNSentryModuleImpl(reactContext); + } + + @Override + @NonNull + public String getName() { + return RNSentryModuleImpl.NAME; + } + + @Override + public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { + this.impl.initNativeSdk(rnOptions, promise); + } + + @Override + public void crash() { + this.impl.crash(); + } + + @Override + public void fetchModules(Promise promise) { + this.impl.fetchModules(promise); + } + + @Override + public void fetchNativeRelease(Promise promise) { + this.impl.fetchNativeRelease(promise); + } + + @Override + public void fetchNativeAppStart(Promise promise) { + this.impl.fetchNativeAppStart(promise); + } + + @Override + public void fetchNativeFrames(Promise promise) { + this.impl.fetchNativeFrames(promise); + } + + @Override + public void captureEnvelope(ReadableArray rawBytes, ReadableMap options, Promise promise) { + this.impl.captureEnvelope(rawBytes, options, promise); + } + + @Override + public void captureScreenshot(Promise promise) { + this.impl.captureScreenshot(promise); + } + + @Override + public void fetchViewHierarchy(Promise promise){ + this.impl.fetchViewHierarchy(promise); + } + + @Override + public void setUser(final ReadableMap user, final ReadableMap otherUserKeys) { + this.impl.setUser(user, otherUserKeys); + } + + @Override + public void addBreadcrumb(final ReadableMap breadcrumb) { + this.impl.addBreadcrumb(breadcrumb); + } + + @Override + public void clearBreadcrumbs() { + this.impl.clearBreadcrumbs(); + } + + @Override + public void setExtra(String key, String extra) { + this.impl.setExtra(key, extra); + } + + @Override + public void setContext(final String key, final ReadableMap context) { + this.impl.setContext(key, context); + } + + @Override + public void setTag(String key, String value) { + this.impl.setTag(key, value); + } + + @Override + public void closeNativeSdk(Promise promise) { + this.impl.closeNativeSdk(promise); + } + + @Override + public void enableNativeFramesTracking() { + this.impl.enableNativeFramesTracking(); + } + + @Override + public void disableNativeFramesTracking() { + this.impl.disableNativeFramesTracking(); + } + + @Override + public void fetchNativeDeviceContexts(Promise promise) { + // Not used on android + } + + @Override + public void fetchNativeSdkInfo(Promise promise) { + // Not used on android + } +} diff --git a/android/src/oldarch/java/io/sentry/react/RNSentryModule.java b/android/src/oldarch/java/io/sentry/react/RNSentryModule.java new file mode 100644 index 000000000..c1f09c5c4 --- /dev/null +++ b/android/src/oldarch/java/io/sentry/react/RNSentryModule.java @@ -0,0 +1,124 @@ +package io.sentry.react; + +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.ReactContextBaseJavaModule; +import com.facebook.react.bridge.ReactMethod; + +public class RNSentryModule extends ReactContextBaseJavaModule { + + private final RNSentryModuleImpl impl; + + RNSentryModule(ReactApplicationContext reactContext) { + super(reactContext); + this.impl = new RNSentryModuleImpl(reactContext); + } + + @Override + public String getName() { + return RNSentryModuleImpl.NAME; + } + + @ReactMethod + public void initNativeSdk(final ReadableMap rnOptions, Promise promise) { + this.impl.initNativeSdk(rnOptions, promise); + } + + @ReactMethod + public void crash() { + this.impl.crash(); + } + + @ReactMethod + public void fetchModules(Promise promise) { + this.impl.fetchModules(promise); + } + + @ReactMethod + public void fetchNativeRelease(Promise promise) { + this.impl.fetchNativeRelease(promise); + } + + @ReactMethod + public void fetchNativeAppStart(Promise promise) { + this.impl.fetchNativeAppStart(promise); + } + + @ReactMethod + public void fetchNativeFrames(Promise promise) { + this.impl.fetchNativeFrames(promise); + } + + @ReactMethod + public void captureEnvelope(ReadableArray rawBytes, ReadableMap options, Promise promise) { + this.impl.captureEnvelope(rawBytes, options, promise); + } + + @ReactMethod + public void captureScreenshot(Promise promise) { + this.impl.captureScreenshot(promise); + } + + @ReactMethod + public void fetchViewHierarchy(Promise promise){ + this.impl.fetchViewHierarchy(promise); + } + + @ReactMethod + public void setUser(final ReadableMap user, final ReadableMap otherUserKeys) { + this.impl.setUser(user, otherUserKeys); + } + + @ReactMethod + public void addBreadcrumb(final ReadableMap breadcrumb) { + this.impl.addBreadcrumb(breadcrumb); + } + + @ReactMethod + public void clearBreadcrumbs() { + this.impl.clearBreadcrumbs(); + } + + @ReactMethod + public void setExtra(String key, String extra) { + this.impl.setExtra(key, extra); + } + + @ReactMethod + public void setContext(final String key, final ReadableMap context) { + this.impl.setContext(key, context); + } + + @ReactMethod + public void setTag(String key, String value) { + this.impl.setTag(key, value); + } + + @ReactMethod + public void closeNativeSdk(Promise promise) { + this.impl.closeNativeSdk(promise); + } + + @ReactMethod + public void enableNativeFramesTracking() { + this.impl.enableNativeFramesTracking(); + } + + @ReactMethod + public void disableNativeFramesTracking() { + this.impl.disableNativeFramesTracking(); + } + + @ReactMethod + public void fetchNativeDeviceContexts(Promise promise) { + // Not used on android + } + + @ReactMethod + public void fetchNativeSdkInfo(Promise promise) { + // Not used on android + } +} diff --git a/ios/RNSentry.h b/ios/RNSentry.h index 6f7df588a..0deb43541 100644 --- a/ios/RNSentry.h +++ b/ios/RNSentry.h @@ -4,6 +4,11 @@ #import "RCTBridge.h" #endif +#import + @interface RNSentry : NSObject +- (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)options + error:(NSError *_Nullable*_Nonnull)errorPointer; + @end diff --git a/ios/RNSentry.m b/ios/RNSentry.mm similarity index 84% rename from ios/RNSentry.m rename to ios/RNSentry.mm index 9c9eed211..80db9de99 100644 --- a/ios/RNSentry.m +++ b/ios/RNSentry.mm @@ -9,6 +9,12 @@ #import #import #import +#import + +// Thanks to this guard, we won't import this header when we build for the old architecture. +#ifdef RCT_NEW_ARCH_ENABLED +#import "RNSentrySpec.h" +#endif @interface SentryTraceContext : NSObject - (nullable instancetype)initWithDict:(NSDictionary *)dictionary; @@ -39,13 +45,40 @@ + (BOOL)requiresMainQueueSetup { RCT_EXPORT_MODULE() - RCT_EXPORT_METHOD(initNativeSdk:(NSDictionary *_Nonnull)options resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSError *error = nil; + SentryOptions* sentryOptions = [self createOptionsWithDictionary:options error:&error]; + if (error != nil) { + reject(@"SentryReactNative", error.localizedDescription, error); + return; + } + + [SentrySDK startWithOptions:sentryOptions]; +#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST + BOOL appIsActive = [[UIApplication sharedApplication] applicationState] == UIApplicationStateActive; +#else + BOOL appIsActive = [[NSApplication sharedApplication] isActive]; +#endif + + // If the app is active/in foreground, and we have not sent the SentryHybridSdkDidBecomeActive notification, send it. + if (appIsActive && !sentHybridSdkDidBecomeActive && (PrivateSentrySDKOnly.options.enableAutoSessionTracking || PrivateSentrySDKOnly.options.enableWatchdogTerminationTracking)) { + [[NSNotificationCenter defaultCenter] + postNotificationName:@"SentryHybridSdkDidBecomeActive" + object:nil]; + + sentHybridSdkDidBecomeActive = true; + } + + resolve(@YES); +} + +- (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull)options + error: (NSError *_Nonnull *_Nonnull) errorPointer +{ SentryBeforeSendEventCallback beforeSend = ^SentryEvent*(SentryEvent *event) { // We don't want to send an event after startup that came from a Unhandled JS Exception of react native // Because we sent it already before the app crashed. @@ -69,10 +102,9 @@ + (BOOL)requiresMainQueueSetup { [mutableOptions removeObjectForKey:@"tracesSampleRate"]; [mutableOptions removeObjectForKey:@"tracesSampler"]; - SentryOptions *sentryOptions = [[SentryOptions alloc] initWithDict:mutableOptions didFailWithError:&error]; - if (error) { - reject(@"SentryReactNative", error.localizedDescription, error); - return; + SentryOptions *sentryOptions = [[SentryOptions alloc] initWithDict:mutableOptions didFailWithError:errorPointer]; + if (*errorPointer != nil) { + return nil; } if ([mutableOptions valueForKey:@"enableNativeCrashHandling"] != nil) { @@ -86,36 +118,16 @@ + (BOOL)requiresMainQueueSetup { } // Enable the App start and Frames tracking measurements - if ([mutableOptions valueForKey:@"enableAutoPerformanceTracking"] != nil) { - BOOL enableAutoPerformanceTracking = (BOOL)[mutableOptions valueForKey:@"enableAutoPerformanceTracking"]; - - PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = enableAutoPerformanceTracking; -#if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST - PrivateSentrySDKOnly.framesTrackingMeasurementHybridSDKMode = enableAutoPerformanceTracking; -#endif - } - - [SentrySDK startWithOptionsObject:sentryOptions]; + if ([mutableOptions valueForKey:@"enableAutoPerformanceTracing"] != nil) { + BOOL enableAutoPerformanceTracing = (BOOL)[mutableOptions valueForKey:@"enableAutoPerformanceTracing"]; + PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = enableAutoPerformanceTracing; #if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST - BOOL appIsActive = [[UIApplication sharedApplication] applicationState] == UIApplicationStateActive; -#else - BOOL appIsActive = [[NSApplication sharedApplication] isActive]; + PrivateSentrySDKOnly.framesTrackingMeasurementHybridSDKMode = enableAutoPerformanceTracing; #endif - - // If the app is active/in foreground, and we have not sent the SentryHybridSdkDidBecomeActive notification, send it. - if (appIsActive && !sentHybridSdkDidBecomeActive && (PrivateSentrySDKOnly.options.enableAutoSessionTracking || PrivateSentrySDKOnly.options.enableOutOfMemoryTracking)) { - [[NSNotificationCenter defaultCenter] - postNotificationName:@"SentryHybridSdkDidBecomeActive" - object:nil]; - - sentHybridSdkDidBecomeActive = true; } - - - - resolve(@YES); + return sentryOptions; } - (void)setEventOriginTag:(SentryEvent *)event { @@ -171,33 +183,27 @@ - (void)setEventEnvironmentTag:(SentryEvent *)event rejecter:(RCTPromiseRejectBlock)reject) { NSLog(@"Bridge call to: deviceContexts"); - NSMutableDictionary *contexts = [NSMutableDictionary new]; + __block NSMutableDictionary *contexts; // Temp work around until sorted out this API in sentry-cocoa. // TODO: If the callback isnt' executed the promise wouldn't be resolved. [SentrySDK configureScope:^(SentryScope * _Nonnull scope) { - NSDictionary *serializedScope = [scope serialize]; - // Scope serializes as 'context' instead of 'contexts' as it does for the event. - NSDictionary *tempContexts = [serializedScope valueForKey:@"context"]; - - NSMutableDictionary *user = [NSMutableDictionary new]; - - NSDictionary *tempUser = [serializedScope valueForKey:@"user"]; - if (tempUser != nil) { - [user addEntriesFromDictionary:[tempUser valueForKey:@"user"]]; - } else { - [user setValue:PrivateSentrySDKOnly.installationID forKey:@"id"]; + NSDictionary *serializedScope = [scope serialize]; + contexts = [serializedScope mutableCopy]; + + NSDictionary *user = [contexts valueForKey:@"user"]; + if (user == nil) { + [contexts + setValue:@{ @"id": PrivateSentrySDKOnly.installationID } + forKey:@"user"]; } - [contexts setValue:user forKey:@"user"]; - if (tempContexts != nil) { - [contexts setValue:tempContexts forKey:@"context"]; - } if (PrivateSentrySDKOnly.options.debug) { NSData *data = [NSJSONSerialization dataWithJSONObject:contexts options:0 error:nil]; NSString *debugContext = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"Contexts: %@", debugContext); } }]; + resolve(contexts); } @@ -311,7 +317,7 @@ - (void)setEventEnvironmentTag:(SentryEvent *)event int counter = 1; for (NSData* raw in rawScreenshots) { NSMutableArray *screenshot = [NSMutableArray arrayWithCapacity:raw.length]; - const char *bytes = [raw bytes]; + const char *bytes = (char*) [raw bytes]; for (int i = 0; i < [raw length]; i++) { [screenshot addObject:[[NSNumber alloc] initWithChar:bytes[i]]]; } @@ -331,6 +337,20 @@ - (void)setEventEnvironmentTag:(SentryEvent *)event resolve(screenshotsArray); } +RCT_EXPORT_METHOD(fetchViewHierarchy: (RCTPromiseResolveBlock)resolve + rejecter: (RCTPromiseRejectBlock)reject) +{ + NSData * rawViewHierarchy = [PrivateSentrySDKOnly captureViewHierarchy]; + + NSMutableArray *viewHierarchy = [NSMutableArray arrayWithCapacity:rawViewHierarchy.length]; + const char *bytes = (char*) [rawViewHierarchy bytes]; + for (int i = 0; i < [rawViewHierarchy length]; i++) { + [viewHierarchy addObject:[[NSNumber alloc] initWithChar:bytes[i]]]; + } + + resolve(viewHierarchy); +} + RCT_EXPORT_METHOD(setUser:(NSDictionary *)userKeys otherUserKeys:(NSDictionary *)userDataKeys ) @@ -369,12 +389,12 @@ - (void)setEventEnvironmentTag:(SentryEvent *)event sentryLevel = kSentryLevelFatal; } else if ([levelString isEqualToString:@"warning"]) { sentryLevel = kSentryLevelWarning; - } else if ([levelString isEqualToString:@"info"]) { - sentryLevel = kSentryLevelInfo; + } else if ([levelString isEqualToString:@"error"]) { + sentryLevel = kSentryLevelError; } else if ([levelString isEqualToString:@"debug"]) { sentryLevel = kSentryLevelDebug; } else { - sentryLevel = kSentryLevelError; + sentryLevel = kSentryLevelInfo; } [breadcrumbInstance setLevel:sentryLevel]; @@ -444,8 +464,17 @@ - (void)setEventEnvironmentTag:(SentryEvent *)event { // Do nothing on iOS, this bridge method only has an effect on android. // If you're starting the Cocoa SDK manually, - // you can set the 'enableAutoPerformanceTracking: true' option and + // you can set the 'enableAutoPerformanceTracing: true' option and // the 'tracesSampleRate' or 'tracesSampler' option. } +// Thanks to this guard, we won't compile this code when we build for the old architecture. +#ifdef RCT_NEW_ARCH_ENABLED +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params +{ + return std::make_shared(params); +} +#endif + @end diff --git a/ios/RNSentry.xcodeproj/project.pbxproj b/ios/RNSentry.xcodeproj/project.pbxproj deleted file mode 100644 index 0f79235dc..000000000 --- a/ios/RNSentry.xcodeproj/project.pbxproj +++ /dev/null @@ -1,472 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 274692BA21B4414400BF91A8 /* RNSentry.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNSentry.m */; }; - 274692BD21B4414400BF91A8 /* libSentryStatic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6387B8561ED8520D0045A84C /* libSentryStatic.a */; }; - 274692BF21B4414400BF91A8 /* RNSentry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = B3E7B5881CC2AC0600A0062D /* RNSentry.h */; }; - 6350257B1E1E845F00408AE7 /* RNSentry.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = B3E7B5881CC2AC0600A0062D /* RNSentry.h */; }; - 6387B8591ED8521B0045A84C /* libSentryStatic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6387B8561ED8520D0045A84C /* libSentryStatic.a */; }; - B3E7B58A1CC2AC0600A0062D /* RNSentry.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNSentry.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 274692B821B4414400BF91A8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 6387B7C11ED84F910045A84C; - remoteInfo = SentryStatic; - }; - 6387B84D1ED8520D0045A84C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 63AA759B1EB8AEF500D153DE; - remoteInfo = Sentry; - }; - 6387B84F1ED8520D0045A84C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 63AA76651EB8CB2F00D153DE; - remoteInfo = SentryTests; - }; - 6387B8551ED8520D0045A84C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 6387B7C21ED84F910045A84C; - remoteInfo = SentryStatic; - }; - 6387B8571ED852170045A84C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */; - proxyType = 1; - remoteGlobalIDString = 6387B7C11ED84F910045A84C; - remoteInfo = SentryStatic; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 274692BE21B4414400BF91A8 /* Copy Headers */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = include/React; - dstSubfolderSpec = 16; - files = ( - 274692BF21B4414400BF91A8 /* RNSentry.h in Copy Headers */, - ); - name = "Copy Headers"; - runOnlyForDeploymentPostprocessing = 0; - }; - 6350257A1E1E845100408AE7 /* Copy Headers */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = include/React; - dstSubfolderSpec = 16; - files = ( - 6350257B1E1E845F00408AE7 /* RNSentry.h in Copy Headers */, - ); - name = "Copy Headers"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 134814201AA4EA6300B7C361 /* libRNSentry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNSentry.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 274692C321B4414400BF91A8 /* libRNSentry-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libRNSentry-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 6387B7971ED84BA70045A84C /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Sentry.xcodeproj; path = Sentry/Sentry.xcodeproj; sourceTree = ""; }; - B3E7B5881CC2AC0600A0062D /* RNSentry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNSentry.h; sourceTree = ""; }; - B3E7B5891CC2AC0600A0062D /* RNSentry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNSentry.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 274692BC21B4414400BF91A8 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 274692BD21B4414400BF91A8 /* libSentryStatic.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 58B511D81A9E6C8500147676 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6387B8591ED8521B0045A84C /* libSentryStatic.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 134814211AA4EA7D00B7C361 /* Products */ = { - isa = PBXGroup; - children = ( - 134814201AA4EA6300B7C361 /* libRNSentry.a */, - 274692C321B4414400BF91A8 /* libRNSentry-tvOS.a */, - ); - name = Products; - sourceTree = ""; - }; - 58B511D21A9E6C8500147676 = { - isa = PBXGroup; - children = ( - 632232581E76C45800F58A1F /* Libraries */, - B3E7B5881CC2AC0600A0062D /* RNSentry.h */, - B3E7B5891CC2AC0600A0062D /* RNSentry.m */, - 134814211AA4EA7D00B7C361 /* Products */, - 6387B7961ED84BA70045A84C /* Frameworks */, - ); - sourceTree = ""; - }; - 632232581E76C45800F58A1F /* Libraries */ = { - isa = PBXGroup; - children = ( - 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */, - ); - name = Libraries; - sourceTree = ""; - }; - 6387B7961ED84BA70045A84C /* Frameworks */ = { - isa = PBXGroup; - children = ( - 6387B7971ED84BA70045A84C /* libz.tbd */, - ); - name = Frameworks; - sourceTree = ""; - }; - 6387B8451ED8520D0045A84C /* Products */ = { - isa = PBXGroup; - children = ( - 6387B84E1ED8520D0045A84C /* Sentry.framework */, - 6387B8501ED8520D0045A84C /* SentryTests.xctest */, - 6387B8561ED8520D0045A84C /* libSentryStatic.a */, - ); - name = Products; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 274692B621B4414400BF91A8 /* RNSentry-tvOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 274692C021B4414400BF91A8 /* Build configuration list for PBXNativeTarget "RNSentry-tvOS" */; - buildPhases = ( - 274692B921B4414400BF91A8 /* Sources */, - 274692BC21B4414400BF91A8 /* Frameworks */, - 274692BE21B4414400BF91A8 /* Copy Headers */, - ); - buildRules = ( - ); - dependencies = ( - 274692B721B4414400BF91A8 /* PBXTargetDependency */, - ); - name = "RNSentry-tvOS"; - productName = RCTDataManager; - productReference = 274692C321B4414400BF91A8 /* libRNSentry-tvOS.a */; - productType = "com.apple.product-type.library.static"; - }; - 58B511DA1A9E6C8500147676 /* RNSentry */ = { - isa = PBXNativeTarget; - buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNSentry" */; - buildPhases = ( - 58B511D71A9E6C8500147676 /* Sources */, - 58B511D81A9E6C8500147676 /* Frameworks */, - 6350257A1E1E845100408AE7 /* Copy Headers */, - ); - buildRules = ( - ); - dependencies = ( - 6387B8581ED852170045A84C /* PBXTargetDependency */, - ); - name = RNSentry; - productName = RCTDataManager; - productReference = 134814201AA4EA6300B7C361 /* libRNSentry.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 58B511D31A9E6C8500147676 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0610; - ORGANIZATIONNAME = Facebook; - TargetAttributes = { - 58B511DA1A9E6C8500147676 = { - CreatedOnToolsVersion = 6.1.1; - }; - }; - }; - buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNSentry" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - English, - en, - ); - mainGroup = 58B511D21A9E6C8500147676; - productRefGroup = 58B511D21A9E6C8500147676; - projectDirPath = ""; - projectReferences = ( - { - ProductGroup = 6387B8451ED8520D0045A84C /* Products */; - ProjectRef = 6387B8441ED8520D0045A84C /* Sentry.xcodeproj */; - }, - ); - projectRoot = ""; - targets = ( - 58B511DA1A9E6C8500147676 /* RNSentry */, - 274692B621B4414400BF91A8 /* RNSentry-tvOS */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXReferenceProxy section */ - 6387B84E1ED8520D0045A84C /* Sentry.framework */ = { - isa = PBXReferenceProxy; - fileType = wrapper.framework; - path = Sentry.framework; - remoteRef = 6387B84D1ED8520D0045A84C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 6387B8501ED8520D0045A84C /* SentryTests.xctest */ = { - isa = PBXReferenceProxy; - fileType = wrapper.cfbundle; - path = SentryTests.xctest; - remoteRef = 6387B84F1ED8520D0045A84C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 6387B8561ED8520D0045A84C /* libSentryStatic.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libSentryStatic.a; - remoteRef = 6387B8551ED8520D0045A84C /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; -/* End PBXReferenceProxy section */ - -/* Begin PBXSourcesBuildPhase section */ - 274692B921B4414400BF91A8 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 274692BA21B4414400BF91A8 /* RNSentry.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 58B511D71A9E6C8500147676 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - B3E7B58A1CC2AC0600A0062D /* RNSentry.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 274692B721B4414400BF91A8 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SentryStatic; - targetProxy = 274692B821B4414400BF91A8 /* PBXContainerItemProxy */; - }; - 6387B8581ED852170045A84C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = SentryStatic; - targetProxy = 6387B8571ED852170045A84C /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 274692C121B4414400BF91A8 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../../react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 274692C221B4414400BF91A8 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../../react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 58B511ED1A9E6C8500147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - 58B511EE1A9E6C8500147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 7.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 58B511F01A9E6C8500147676 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../../react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RNSentry; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 58B511F11A9E6C8500147676 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../../react-native/React/**", - ); - LIBRARY_SEARCH_PATHS = "$(inherited)"; - OTHER_LDFLAGS = "-ObjC"; - PRODUCT_NAME = RNSentry; - SKIP_INSTALL = YES; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 274692C021B4414400BF91A8 /* Build configuration list for PBXNativeTarget "RNSentry-tvOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 274692C121B4414400BF91A8 /* Debug */, - 274692C221B4414400BF91A8 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNSentry" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511ED1A9E6C8500147676 /* Debug */, - 58B511EE1A9E6C8500147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNSentry" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 58B511F01A9E6C8500147676 /* Debug */, - 58B511F11A9E6C8500147676 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 58B511D31A9E6C8500147676 /* Project object */; -} diff --git a/package.json b/package.json index f67c7b89f..05a071109 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@sentry/react-native", "homepage": "https://github.com/getsentry/sentry-react-native", "repository": "https://github.com/getsentry/sentry-react-native", - "version": "4.15.0", + "version": "5.0.0-rc.1", "description": "Official Sentry SDK for react-native", "typings": "dist/js/index.d.ts", "types": "dist/js/index.d.ts", @@ -38,25 +38,25 @@ "When bumping make sure to update the version of react, i.e: https://github.com/facebook/react-native/blob/v0.56.0/package.json" ], "peerDependencies": { - "react": ">=16.4.1", - "react-native": ">=0.56.0" + "react": ">=17.0.0", + "react-native": ">=0.65.0" }, "dependencies": { "@sentry/browser": "7.37.2", - "@sentry/cli": "1.74.4", + "@sentry/cli": "2.10.0", "@sentry/core": "7.37.2", "@sentry/hub": "7.37.2", "@sentry/integrations": "7.37.2", "@sentry/react": "7.37.2", "@sentry/tracing": "7.37.2", "@sentry/types": "7.37.2", - "@sentry/utils": "7.37.2", - "@sentry/wizard": "1.4.0" + "@sentry/utils": "7.37.2" }, "devDependencies": { "@sentry-internal/eslint-config-sdk": "7.37.2", "@sentry-internal/eslint-plugin-sdk": "7.37.2", "@sentry/typescript": "^5.20.1", + "@sentry/wizard": "2.2.0", "@types/jest": "^29.2.5", "@types/react": "^18.0.25", "babel-jest": "^29.3.1", @@ -64,6 +64,7 @@ "eslint-plugin-react": "^7.20.6", "eslint-plugin-react-native": "^3.8.1", "jest": "^29.3.1", + "jest-environment-jsdom": "^29.4.1", "prettier": "^2.0.5", "react": "18.2.0", "react-native": "0.71.0", @@ -73,18 +74,12 @@ "typescript": "3.8.3" }, "rnpm": { - "commands": { - "postlink": "node node_modules/@sentry/wizard/dist/bin.js -i reactNative -p ios android", - "postunlink": "node node_modules/@sentry/wizard/dist/bin.js -i reactNative -p ios android --uninstall" - }, + "commands": {}, "android": { - "packageInstance": "new RNSentryPackage()" + "packageInstance": "new RNSentryPackage()", + "packageImportPath": "import io.sentry.react.RNSentryPackage;" }, - "ios": { - "sharedLibraries": [ - "libz" - ] - } + "ios": {} }, "jest": { "collectCoverage": true, @@ -102,11 +97,20 @@ "js" ], "testPathIgnorePatterns": [ - "/sample/" + "/sample/", + "/test/e2e/" ], "testEnvironment": "node", "testMatch": [ "**/*.test.(ts|tsx)" ] + }, + "codegenConfig": { + "name": "RNSentrySpec", + "type": "modules", + "jsSrcsDir": "src", + "android": { + "javaPackageName": "io.sentry.react" + } } } diff --git a/react-native.config.js b/react-native.config.js index f85fa01be..d307073e1 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -1,18 +1,11 @@ module.exports = { dependency: { platforms: { - ios: { - sharedLibraries: ['libz'] - }, + ios: {}, android: { - packageInstance: 'new RNSentryPackage()' + packageInstance: 'new RNSentryPackage()', + packageImportPath: 'import io.sentry.react.RNSentryPackage;' } - }, - hooks: { - postlink: - 'node node_modules/@sentry/wizard/dist/bin.js -i reactNative -p ios android', - postunlink: - 'node node_modules/@sentry/wizard/dist/bin.js -i reactNative -p ios android --uninstall' } } }; diff --git a/sample-new-architecture/.eslintrc.js b/sample-new-architecture/.eslintrc.js new file mode 100644 index 000000000..3d4d370fc --- /dev/null +++ b/sample-new-architecture/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + root: true, + extends: '@react-native-community', + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint'], + overrides: [ + { + files: ['*.ts', '*.tsx'], + rules: { + '@typescript-eslint/no-shadow': ['error'], + 'no-shadow': 'off', + 'no-undef': 'off', + quotes: [2, 'single', { avoidEscape: true }], + }, + }, + ], +}; diff --git a/sample-new-architecture/.gitignore b/sample-new-architecture/.gitignore new file mode 100644 index 000000000..16f8c3077 --- /dev/null +++ b/sample-new-architecture/.gitignore @@ -0,0 +1,63 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +ios/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ +*.keystore +!debug.keystore + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +/ios/Pods/ +/vendor/bundle/ + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* diff --git a/sample-new-architecture/.prettierrc.js b/sample-new-architecture/.prettierrc.js new file mode 100644 index 000000000..2ae7b381e --- /dev/null +++ b/sample-new-architecture/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + arrowParens: 'avoid', + bracketSameLine: true, + bracketSpacing: true, + singleQuote: true, + trailingComma: 'all', +}; diff --git a/sample-new-architecture/.watchmanconfig b/sample-new-architecture/.watchmanconfig new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/sample-new-architecture/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/sample-new-architecture/Gemfile b/sample-new-architecture/Gemfile new file mode 100644 index 000000000..3a766de9c --- /dev/null +++ b/sample-new-architecture/Gemfile @@ -0,0 +1,6 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby File.read(File.join(__dir__, '_ruby-version')).strip + +gem 'cocoapods', '~> 1.11', '>= 1.11.3' diff --git a/sample-new-architecture/Gemfile.lock b/sample-new-architecture/Gemfile.lock new file mode 100644 index 000000000..51bf55aa6 --- /dev/null +++ b/sample-new-architecture/Gemfile.lock @@ -0,0 +1,100 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.5) + rexml + activesupport (6.1.7) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) + atomos (0.1.3) + claide (1.1.0) + cocoapods (1.11.3) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.11.3) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 1.4.0, < 2.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.4.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 1.0, < 3.0) + xcodeproj (>= 1.21.0, < 2.0) + cocoapods-core (1.11.3) + activesupport (>= 5.0, < 7) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (1.6.3) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored2 (3.1.2) + concurrent-ruby (1.1.10) + escape (0.0.4) + ethon (0.15.0) + ffi (>= 1.15.0) + ffi (1.15.5) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + httpclient (2.8.3) + i18n (1.12.0) + concurrent-ruby (~> 1.0) + json (2.6.2) + minitest (5.16.3) + molinillo (0.8.0) + nanaimo (0.3.0) + nap (1.1.0) + netrc (0.11.0) + public_suffix (4.0.7) + rexml (3.2.5) + ruby-macho (2.5.1) + typhoeus (1.4.0) + ethon (>= 0.9.0) + tzinfo (2.0.5) + concurrent-ruby (~> 1.0) + xcodeproj (1.22.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + rexml (~> 3.2.4) + zeitwerk (2.6.1) + +PLATFORMS + arm64-darwin-21 + +DEPENDENCIES + cocoapods (~> 1.11, >= 1.11.2) + +RUBY VERSION + ruby 2.7.6p219 + +BUNDLED WITH + 2.3.11 diff --git a/sample-new-architecture/__tests__/App-test.tsx b/sample-new-architecture/__tests__/App-test.tsx new file mode 100644 index 000000000..b71837e8e --- /dev/null +++ b/sample-new-architecture/__tests__/App-test.tsx @@ -0,0 +1,13 @@ +/** + * @format + */ + +import 'react-native'; +import React from 'react'; + +// Note: test renderer must be required after react-native. +import renderer from 'react-test-renderer'; + +it('dummy test', () => { + renderer.create(
); +}); diff --git a/sample-new-architecture/_bundle/config b/sample-new-architecture/_bundle/config new file mode 100644 index 000000000..848943bb5 --- /dev/null +++ b/sample-new-architecture/_bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/sample-new-architecture/_node-version b/sample-new-architecture/_node-version new file mode 100644 index 000000000..8351c1939 --- /dev/null +++ b/sample-new-architecture/_node-version @@ -0,0 +1 @@ +14 diff --git a/sample-new-architecture/_ruby-version b/sample-new-architecture/_ruby-version new file mode 100644 index 000000000..49cdd668e --- /dev/null +++ b/sample-new-architecture/_ruby-version @@ -0,0 +1 @@ +2.7.6 diff --git a/sample-new-architecture/android/app/build.gradle b/sample-new-architecture/android/app/build.gradle new file mode 100644 index 000000000..0b37d64a8 --- /dev/null +++ b/sample-new-architecture/android/app/build.gradle @@ -0,0 +1,182 @@ +apply plugin: "com.android.application" +apply plugin: "com.facebook.react" + +import com.android.build.OutputFile + +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '..' + // root = file("../") + // The folder where the react-native NPM package is. Default is ../node_modules/react-native + // reactNativeDir = file("../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen + // codegenDir = file("../node_modules/react-native-codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js + // cliFile = file("../node_modules/react-native/cli.js") + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] +} + +project.ext.sentryCli = [ + collectModulesScript: "../../../dist/js/tools/collectModules.js", + modulesPaths: [ + "node_modules", + "../..", + ], + skipCollectModules: false, +] + +apply from: "../../../sentry.gradle" + +/** + * Set this to true to create four separate APKs instead of one, + * one for each native architecture. This is useful if you don't + * use App Bundles (https://developer.android.com/guide/app-bundle/) + * and want to have separate APKs to upload to the Play Store. + */ +def enableSeparateBuildPerCPUArchitecture = false + +/** + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore. + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'org.webkit:android-jsc:+' + +/** + * Architectures to build native code for. + */ +def reactNativeArchitectures() { + def value = project.getProperties().get("reactNativeArchitectures") + return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] +} + +android { + ndkVersion rootProject.ext.ndkVersion + + compileSdkVersion rootProject.ext.compileSdkVersion + + namespace "com.samplenewarchitecture" + defaultConfig { + applicationId "com.samplenewarchitecture" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + + splits { + abi { + reset() + enable enableSeparateBuildPerCPUArchitecture + universalApk false // If true, also generate a universal APK + include (*reactNativeArchitectures()) + } + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } + + // applicationVariants are e.g. debug, release + applicationVariants.all { variant -> + variant.outputs.each { output -> + // For each separate APK per architecture, set a unique version code as described here: + // https://developer.android.com/studio/build/configure-apk-splits.html + // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc. + def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] + def abi = output.getFilter(OutputFile.ABI) + if (abi != null) { // null for the universal-debug, universal-release variants + output.versionCodeOverride = + defaultConfig.versionCode * 1000 + versionCodes.get(abi) + } + + } + } + + +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + + implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" + + debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") + debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { + exclude group:'com.squareup.okhttp3', module:'okhttp' + } + debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") + + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } +} + +apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) + +android { + externalNativeBuild { + cmake { + path "src/main/jni/CMakeLists.txt" + } + } +} diff --git a/sample-new-architecture/android/app/debug.keystore b/sample-new-architecture/android/app/debug.keystore new file mode 100644 index 000000000..364e105ed Binary files /dev/null and b/sample-new-architecture/android/app/debug.keystore differ diff --git a/sample-new-architecture/android/app/proguard-rules.pro b/sample-new-architecture/android/app/proguard-rules.pro new file mode 100644 index 000000000..11b025724 --- /dev/null +++ b/sample-new-architecture/android/app/proguard-rules.pro @@ -0,0 +1,10 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: diff --git a/sample-new-architecture/android/app/src/debug/AndroidManifest.xml b/sample-new-architecture/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 000000000..4b185bc15 --- /dev/null +++ b/sample-new-architecture/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sample-new-architecture/android/app/src/debug/java/com/samplenewarchitecture/ReactNativeFlipper.java b/sample-new-architecture/android/app/src/debug/java/com/samplenewarchitecture/ReactNativeFlipper.java new file mode 100644 index 000000000..0d9fb8a02 --- /dev/null +++ b/sample-new-architecture/android/app/src/debug/java/com/samplenewarchitecture/ReactNativeFlipper.java @@ -0,0 +1,75 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + */ +package com.samplenewarchitecture; + +import android.content.Context; +import com.facebook.flipper.android.AndroidFlipperClient; +import com.facebook.flipper.android.utils.FlipperUtils; +import com.facebook.flipper.core.FlipperClient; +import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; +import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; +import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; +import com.facebook.flipper.plugins.inspector.DescriptorMapping; +import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; +import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; +import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; +import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; +import com.facebook.react.ReactInstanceEventListener; +import com.facebook.react.ReactInstanceManager; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.modules.network.NetworkingModule; +import okhttp3.OkHttpClient; + +/** + * Class responsible of loading Flipper inside your React Native application. This is the debug + * flavor of it. Here you can add your own plugins and customize the Flipper setup. + */ +public class ReactNativeFlipper { + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + if (FlipperUtils.shouldEnableFlipper(context)) { + final FlipperClient client = AndroidFlipperClient.getInstance(context); + + client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); + client.addPlugin(new DatabasesFlipperPlugin(context)); + client.addPlugin(new SharedPreferencesFlipperPlugin(context)); + client.addPlugin(CrashReporterPlugin.getInstance()); + + NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); + NetworkingModule.setCustomClientBuilder( + new NetworkingModule.CustomClientBuilder() { + @Override + public void apply(OkHttpClient.Builder builder) { + builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); + } + }); + client.addPlugin(networkFlipperPlugin); + client.start(); + + // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized + // Hence we run if after all native modules have been initialized + ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); + if (reactContext == null) { + reactInstanceManager.addReactInstanceEventListener( + new ReactInstanceEventListener() { + @Override + public void onReactContextInitialized(ReactContext reactContext) { + reactInstanceManager.removeReactInstanceEventListener(this); + reactContext.runOnNativeModulesQueueThread( + new Runnable() { + @Override + public void run() { + client.addPlugin(new FrescoFlipperPlugin()); + } + }); + } + }); + } else { + client.addPlugin(new FrescoFlipperPlugin()); + } + } + } +} diff --git a/sample-new-architecture/android/app/src/main/AndroidManifest.xml b/sample-new-architecture/android/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..4122f36a5 --- /dev/null +++ b/sample-new-architecture/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + diff --git a/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/MainActivity.java b/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/MainActivity.java new file mode 100644 index 000000000..906ed3cd6 --- /dev/null +++ b/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/MainActivity.java @@ -0,0 +1,41 @@ +package com.samplenewarchitecture; + +import android.os.Bundle; +import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactActivityDelegate; + +public class MainActivity extends ReactActivity { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "sampleNewArchitecture"; + } + + /** + * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link + * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React + * (aka React 18) with two boolean flags. + */ + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new DefaultReactActivityDelegate( + this, + getMainComponentName(), + // If you opted-in for the New Architecture, we enable the Fabric Renderer. + DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled + // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18). + DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled + ); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(null); + } +} diff --git a/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/MainApplication.java b/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/MainApplication.java new file mode 100644 index 000000000..8e772e3ba --- /dev/null +++ b/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/MainApplication.java @@ -0,0 +1,73 @@ +package com.samplenewarchitecture; + +import android.app.Application; +import com.facebook.react.PackageList; +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactNativeHost; +import com.facebook.soloader.SoLoader; +import java.util.List; + +import io.sentry.react.RNSentryPackage; + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = + new DefaultReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + for (ReactPackage pkg : packages) { + if (pkg instanceof RNSentryPackage) { + return packages; + } + } + + packages.add(new RNSentryPackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + + @Override + protected boolean isNewArchEnabled() { + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + } + + @Override + protected Boolean isHermesEnabled() { + return BuildConfig.IS_HERMES_ENABLED; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + DefaultNewArchitectureEntryPoint.load(); + } + ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } + +} diff --git a/sample-new-architecture/android/app/src/main/jni/CMakeLists.txt b/sample-new-architecture/android/app/src/main/jni/CMakeLists.txt new file mode 100644 index 000000000..4e34bb3db --- /dev/null +++ b/sample-new-architecture/android/app/src/main/jni/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# This CMake file is the default used by apps and is placed inside react-native +# to encapsulate it from user space (so you won't need to touch C++/Cmake code at all on Android). +# +# If you wish to customize it (because you want to manually link a C++ library or pass a custom +# compilation flag) you can: +# +# 1. Copy this CMake file inside the `android/app/src/main/jni` folder of your project +# 2. Copy the OnLoad.cpp (in this same folder) file inside the same folder as above. +# 3. Extend your `android/app/build.gradle` as follows +# +# android { +# // Other config here... +# externalNativeBuild { +# cmake { +# path "src/main/jni/CMakeLists.txt" +# } +# } +# } + +cmake_minimum_required(VERSION 3.13) + +# Define the library name here. +project(appmodules) + +# This file includes all the necessary to let you build your application with the New Architecture. +include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake) + +# App needs to add and link against tm (TurboModules) folder +add_subdirectory(${REACT_ANDROID_DIR}/../../../tm/ tm_build) +target_link_libraries(${CMAKE_PROJECT_NAME} tm) diff --git a/sample-new-architecture/android/app/src/main/jni/OnLoad.cpp b/sample-new-architecture/android/app/src/main/jni/OnLoad.cpp new file mode 100644 index 000000000..6e1d15669 --- /dev/null +++ b/sample-new-architecture/android/app/src/main/jni/OnLoad.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// This C++ file is part of the default configuration used by apps and is placed +// inside react-native to encapsulate it from user space (so you won't need to +// touch C++/Cmake code at all on Android). +// +// If you wish to customize it (because you want to manually link a C++ library +// or pass a custom compilation flag) you can: +// +// 1. Copy this CMake file inside the `android/app/src/main/jni` folder of your +// project +// 2. Copy the OnLoad.cpp (in this same folder) file inside the same folder as +// above. +// 3. Extend your `android/app/build.gradle` as follows +// +// android { +// // Other config here... +// externalNativeBuild { +// cmake { +// path "src/main/jni/CMakeLists.txt" +// } +// } +// } + +#include +#include +#include +#include +#include +#include + +namespace facebook { +namespace react { + +void registerComponents( + std::shared_ptr registry) { + // Custom Fabric Components go here. You can register custom + // components coming from your App or from 3rd party libraries here. + // + // providerRegistry->add(concreteComponentDescriptorProvider< + // AocViewerComponentDescriptor>()); + + // By default we just use the components autolinked by RN CLI + rncli_registerProviders(registry); +} + +std::shared_ptr cxxModuleProvider( + const std::string &name, + const std::shared_ptr &jsInvoker) { + // Not implemented yet: provide pure-C++ NativeModules here. + if (name == "NativeSampleModule") + { + return std::make_shared(jsInvoker); + } + return nullptr; +} + +std::shared_ptr javaModuleProvider( + const std::string &name, + const JavaTurboModule::InitParams ¶ms) { + // Here you can provide your own module provider for TurboModules coming from + // either your application or from external libraries. The approach to follow + // is similar to the following (for a library called `samplelibrary`): + // + // auto module = samplelibrary_ModuleProvider(moduleName, params); + // if (module != nullptr) { + // return module; + // } + // return rncore_ModuleProvider(moduleName, params); + + // By default we just use the module providers autolinked by RN CLI + return rncli_ModuleProvider(name, params); +} + +} // namespace react +} // namespace facebook + +JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) { + return facebook::jni::initialize(vm, [] { + facebook::react::DefaultTurboModuleManagerDelegate::cxxModuleProvider = + &facebook::react::cxxModuleProvider; + facebook::react::DefaultTurboModuleManagerDelegate::javaModuleProvider = + &facebook::react::javaModuleProvider; + facebook::react::DefaultComponentsRegistry:: + registerComponentDescriptorsFromEntryPoint = + &facebook::react::registerComponents; + }); +} diff --git a/sample-new-architecture/android/app/src/main/res/drawable/rn_edit_text_material.xml b/sample-new-architecture/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 000000000..f35d99620 --- /dev/null +++ b/sample-new-architecture/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/sample-new-architecture/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..a2f590828 Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/sample-new-architecture/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 000000000..1b5239980 Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/sample-new-architecture/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..ff10afd6e Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/sample-new-architecture/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 000000000..115a4c768 Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/sample-new-architecture/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..dcd3cd808 Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/sample-new-architecture/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 000000000..459ca609d Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sample-new-architecture/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..8ca12fe02 Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/sample-new-architecture/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..8e19b410a Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sample-new-architecture/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..b824ebdd4 Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/sample-new-architecture/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/sample-new-architecture/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 000000000..4c19a13c2 Binary files /dev/null and b/sample-new-architecture/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/sample-new-architecture/android/app/src/main/res/values/strings.xml b/sample-new-architecture/android/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..08f35f887 --- /dev/null +++ b/sample-new-architecture/android/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + sampleNewArchitecture + diff --git a/sample-new-architecture/android/app/src/main/res/values/styles.xml b/sample-new-architecture/android/app/src/main/res/values/styles.xml new file mode 100644 index 000000000..7ba83a2ad --- /dev/null +++ b/sample-new-architecture/android/app/src/main/res/values/styles.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/sample-new-architecture/android/app/src/release/java/com/samplenewarchitecture/ReactNativeFlipper.java b/sample-new-architecture/android/app/src/release/java/com/samplenewarchitecture/ReactNativeFlipper.java new file mode 100644 index 000000000..9292b4aa0 --- /dev/null +++ b/sample-new-architecture/android/app/src/release/java/com/samplenewarchitecture/ReactNativeFlipper.java @@ -0,0 +1,18 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + */ +package com.samplenewarchitecture; +import android.content.Context; +import com.facebook.react.ReactInstanceManager; +/** + * Class responsible of loading Flipper inside your React Native application. This is the release + * flavor of it so it's empty as we don't want to load Flipper. + */ +public class ReactNativeFlipper { + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + // Do nothing as we don't want to initialize Flipper on Release. + } +} diff --git a/sample-new-architecture/android/build.gradle b/sample-new-architecture/android/build.gradle new file mode 100644 index 000000000..67d887b03 --- /dev/null +++ b/sample-new-architecture/android/build.gradle @@ -0,0 +1,21 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + ext { + buildToolsVersion = "33.0.0" + minSdkVersion = 21 + compileSdkVersion = 33 + targetSdkVersion = 33 + + // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. + ndkVersion = "23.1.7779620" + } + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:7.3.1") + classpath("com.facebook.react:react-native-gradle-plugin") + } +} diff --git a/sample-new-architecture/android/gradle.properties b/sample-new-architecture/android/gradle.properties new file mode 100644 index 000000000..6b6e1f852 --- /dev/null +++ b/sample-new-architecture/android/gradle.properties @@ -0,0 +1,44 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + +# Version of flipper SDK to use with React Native +FLIPPER_VERSION=0.164.0 + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=true + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/sample-new-architecture/android/gradle/wrapper/gradle-wrapper.jar b/sample-new-architecture/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..41d9927a4 Binary files /dev/null and b/sample-new-architecture/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/sample-new-architecture/android/gradle/wrapper/gradle-wrapper.properties b/sample-new-architecture/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..8fad3f5a9 --- /dev/null +++ b/sample-new-architecture/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/sample-new-architecture/android/gradlew b/sample-new-architecture/android/gradlew new file mode 100755 index 000000000..1b6c78733 --- /dev/null +++ b/sample-new-architecture/android/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/sample-new-architecture/android/gradlew.bat b/sample-new-architecture/android/gradlew.bat new file mode 100644 index 000000000..ac1b06f93 --- /dev/null +++ b/sample-new-architecture/android/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/sample-new-architecture/android/sentry.properties b/sample-new-architecture/android/sentry.properties new file mode 100644 index 000000000..0cdf17015 --- /dev/null +++ b/sample-new-architecture/android/sentry.properties @@ -0,0 +1,4 @@ +#defaults.url=https://sentry.io/ +defaults.org=sentry-sdks +defaults.project=sentry-react-native +#auth.token= diff --git a/sample-new-architecture/android/settings.gradle b/sample-new-architecture/android/settings.gradle new file mode 100644 index 000000000..ad4844d2a --- /dev/null +++ b/sample-new-architecture/android/settings.gradle @@ -0,0 +1,4 @@ +rootProject.name = 'sampleNewArchitecture' +apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) +include ':app' +includeBuild('../node_modules/react-native-gradle-plugin') diff --git a/sample-new-architecture/app.json b/sample-new-architecture/app.json new file mode 100644 index 000000000..9f112deab --- /dev/null +++ b/sample-new-architecture/app.json @@ -0,0 +1,4 @@ +{ + "name": "sampleNewArchitecture", + "displayName": "sampleNewArchitecture" +} diff --git a/sample-new-architecture/babel.config.js b/sample-new-architecture/babel.config.js new file mode 100644 index 000000000..232253cc3 --- /dev/null +++ b/sample-new-architecture/babel.config.js @@ -0,0 +1,13 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], + plugins: [ + [ + 'module-resolver', + { + alias: { + '@sentry/react-native': '../dist/js', + }, + }, + ], + ], +}; diff --git a/sample-new-architecture/index.js b/sample-new-architecture/index.js new file mode 100644 index 000000000..e1dd8be53 --- /dev/null +++ b/sample-new-architecture/index.js @@ -0,0 +1,10 @@ +/** + * @format + */ + +import { AppRegistry } from 'react-native'; + +import App from './src/App'; +import { name as appName } from './app.json'; + +AppRegistry.registerComponent(appName, () => App); diff --git a/sample-new-architecture/ios/Podfile b/sample-new-architecture/ios/Podfile new file mode 100644 index 000000000..f4697edb8 --- /dev/null +++ b/sample-new-architecture/ios/Podfile @@ -0,0 +1,66 @@ +require_relative '../node_modules/react-native/scripts/react_native_pods' +require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' + +platform :ios, min_ios_version_supported +prepare_react_native_project! +# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set. +# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded +# +# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js` +# ```js +# module.exports = { +# dependencies: { +# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}), +# ``` +flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled +linkage = ENV['USE_FRAMEWORKS'] +if linkage != nil + Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green + use_frameworks! :linkage => linkage.to_sym +end + +target 'sampleNewArchitecture' do + config = use_native_modules! + + # Flags change depending on the env values. + flags = get_default_flags() + + use_react_native!( + :path => config[:reactNativePath], + # Hermes is now enabled by default. Disable by setting this flag to false. + # Upcoming versions of React Native may rely on get_default_flags(), but + # we make it explicit here to aid in the React Native upgrade process. + :hermes_enabled => flags[:hermes_enabled], + :fabric_enabled => flags[:fabric_enabled], + # Enables Flipper. + # + # Note that if you have use_frameworks! enabled, Flipper will not work and + # you should disable the next line. + :flipper_configuration => flipper_config, + # An absolute path to your application root. + :app_path => "#{Pod::Config.instance.installation_root}/.." + ) + + if ENV['RCT_NEW_ARCH_ENABLED'] == '1' + pod 'AppTurboModules', :path => "./../tm" + end + + if !ENV['TEST'] + pod 'RNSentry', :path => '../..' + end + + target 'sampleNewArchitectureTests' do + inherit! :complete + # Pods for testing + end + + post_install do |installer| + react_native_post_install( + installer, + # Set `mac_catalyst_enabled` to `true` in order to apply patches + # necessary for Mac Catalyst builds + :mac_catalyst_enabled => false + ) + __apply_Xcode_12_5_M1_post_install_workaround(installer) + end +end diff --git a/sample-new-architecture/ios/_xcode.env b/sample-new-architecture/ios/_xcode.env new file mode 100644 index 000000000..3d5782c71 --- /dev/null +++ b/sample-new-architecture/ios/_xcode.env @@ -0,0 +1,11 @@ +# This `.xcode.env` file is versioned and is used to source the environment +# used when running script phases inside Xcode. +# To customize your local environment, you can create an `.xcode.env.local` +# file that is not versioned. + +# NODE_BINARY variable contains the PATH to the node executable. +# +# Customize the NODE_BINARY variable here. +# For example, to use nvm with brew, add the following line +# . "$(brew --prefix nvm)/nvm.sh" --no-use +export NODE_BINARY=$(command -v node) diff --git a/sample-new-architecture/ios/sampleNewArchitecture.xcodeproj/project.pbxproj b/sample-new-architecture/ios/sampleNewArchitecture.xcodeproj/project.pbxproj new file mode 100644 index 000000000..d3b74b265 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture.xcodeproj/project.pbxproj @@ -0,0 +1,719 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 00E356F31AD99517003FC87E /* sampleNewArchitectureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* sampleNewArchitectureTests.m */; }; + 0C80B921A6F3F58F76C31292 /* libPods-sampleNewArchitecture.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-sampleNewArchitecture.a */; }; + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; + 7699B88040F8A987B510C191 /* libPods-sampleNewArchitecture-sampleNewArchitectureTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-sampleNewArchitecture-sampleNewArchitectureTests.a */; }; + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 13B07F861A680F5B00A75B9A; + remoteInfo = sampleNewArchitecture; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 00E356EE1AD99517003FC87E /* sampleNewArchitectureTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = sampleNewArchitectureTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* sampleNewArchitectureTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = sampleNewArchitectureTests.m; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* sampleNewArchitecture.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = sampleNewArchitecture.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = sampleNewArchitecture/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = sampleNewArchitecture/AppDelegate.mm; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = sampleNewArchitecture/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = sampleNewArchitecture/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = sampleNewArchitecture/main.m; sourceTree = ""; }; + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-sampleNewArchitecture-sampleNewArchitectureTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-sampleNewArchitecture-sampleNewArchitectureTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B4392A12AC88292D35C810B /* Pods-sampleNewArchitecture.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-sampleNewArchitecture.debug.xcconfig"; path = "Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-sampleNewArchitecture.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-sampleNewArchitecture.release.xcconfig"; path = "Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture.release.xcconfig"; sourceTree = ""; }; + 5B7EB9410499542E8C5724F5 /* Pods-sampleNewArchitecture-sampleNewArchitectureTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-sampleNewArchitecture-sampleNewArchitectureTests.debug.xcconfig"; path = "Target Support Files/Pods-sampleNewArchitecture-sampleNewArchitectureTests/Pods-sampleNewArchitecture-sampleNewArchitectureTests.debug.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-sampleNewArchitecture.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-sampleNewArchitecture.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = sampleNewArchitecture/LaunchScreen.storyboard; sourceTree = ""; }; + 89C6BE57DB24E9ADA2F236DE /* Pods-sampleNewArchitecture-sampleNewArchitectureTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-sampleNewArchitecture-sampleNewArchitectureTests.release.xcconfig"; path = "Target Support Files/Pods-sampleNewArchitecture-sampleNewArchitectureTests/Pods-sampleNewArchitecture-sampleNewArchitectureTests.release.xcconfig"; sourceTree = ""; }; + ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 00E356EB1AD99517003FC87E /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7699B88040F8A987B510C191 /* libPods-sampleNewArchitecture-sampleNewArchitectureTests.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0C80B921A6F3F58F76C31292 /* libPods-sampleNewArchitecture.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 00E356EF1AD99517003FC87E /* sampleNewArchitectureTests */ = { + isa = PBXGroup; + children = ( + 00E356F21AD99517003FC87E /* sampleNewArchitectureTests.m */, + 00E356F01AD99517003FC87E /* Supporting Files */, + ); + path = sampleNewArchitectureTests; + sourceTree = ""; + }; + 00E356F01AD99517003FC87E /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 00E356F11AD99517003FC87E /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 13B07FAE1A68108700A75B9A /* sampleNewArchitecture */ = { + isa = PBXGroup; + children = ( + 13B07FAF1A68108700A75B9A /* AppDelegate.h */, + 13B07FB01A68108700A75B9A /* AppDelegate.mm */, + 13B07FB51A68108700A75B9A /* Images.xcassets */, + 13B07FB61A68108700A75B9A /* Info.plist */, + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, + 13B07FB71A68108700A75B9A /* main.m */, + ); + name = sampleNewArchitecture; + sourceTree = ""; + }; + 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { + isa = PBXGroup; + children = ( + ED297162215061F000B7C4FE /* JavaScriptCore.framework */, + 5DCACB8F33CDC322A6C60F78 /* libPods-sampleNewArchitecture.a */, + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-sampleNewArchitecture-sampleNewArchitectureTests.a */, + ); + name = Frameworks; + sourceTree = ""; + }; + 832341AE1AAA6A7D00B99B32 /* Libraries */ = { + isa = PBXGroup; + children = ( + ); + name = Libraries; + sourceTree = ""; + }; + 83CBB9F61A601CBA00E9B192 = { + isa = PBXGroup; + children = ( + 13B07FAE1A68108700A75B9A /* sampleNewArchitecture */, + 832341AE1AAA6A7D00B99B32 /* Libraries */, + 00E356EF1AD99517003FC87E /* sampleNewArchitectureTests */, + 83CBBA001A601CBA00E9B192 /* Products */, + 2D16E6871FA4F8E400B85C8A /* Frameworks */, + BBD78D7AC51CEA395F1C20DB /* Pods */, + ); + indentWidth = 2; + sourceTree = ""; + tabWidth = 2; + usesTabs = 0; + }; + 83CBBA001A601CBA00E9B192 /* Products */ = { + isa = PBXGroup; + children = ( + 13B07F961A680F5B00A75B9A /* sampleNewArchitecture.app */, + 00E356EE1AD99517003FC87E /* sampleNewArchitectureTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + BBD78D7AC51CEA395F1C20DB /* Pods */ = { + isa = PBXGroup; + children = ( + 3B4392A12AC88292D35C810B /* Pods-sampleNewArchitecture.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-sampleNewArchitecture.release.xcconfig */, + 5B7EB9410499542E8C5724F5 /* Pods-sampleNewArchitecture-sampleNewArchitectureTests.debug.xcconfig */, + 89C6BE57DB24E9ADA2F236DE /* Pods-sampleNewArchitecture-sampleNewArchitectureTests.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 00E356ED1AD99517003FC87E /* sampleNewArchitectureTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "sampleNewArchitectureTests" */; + buildPhases = ( + A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */, + 00E356EA1AD99517003FC87E /* Sources */, + 00E356EB1AD99517003FC87E /* Frameworks */, + 00E356EC1AD99517003FC87E /* Resources */, + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */, + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */, + ); + buildRules = ( + ); + dependencies = ( + 00E356F51AD99517003FC87E /* PBXTargetDependency */, + ); + name = sampleNewArchitectureTests; + productName = sampleNewArchitectureTests; + productReference = 00E356EE1AD99517003FC87E /* sampleNewArchitectureTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 13B07F861A680F5B00A75B9A /* sampleNewArchitecture */ = { + isa = PBXNativeTarget; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "sampleNewArchitecture" */; + buildPhases = ( + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + FD10A7F022414F080027D42C /* Start Packager */, + 13B07F871A680F5B00A75B9A /* Sources */, + 13B07F8C1A680F5B00A75B9A /* Frameworks */, + 13B07F8E1A680F5B00A75B9A /* Resources */, + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + 8152B8B60F6641B996EA3E8F /* Upload Debug Symbols to Sentry */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = sampleNewArchitecture; + productName = sampleNewArchitecture; + productReference = 13B07F961A680F5B00A75B9A /* sampleNewArchitecture.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 83CBB9F71A601CBA00E9B192 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1210; + TargetAttributes = { + 00E356ED1AD99517003FC87E = { + CreatedOnToolsVersion = 6.2; + TestTargetID = 13B07F861A680F5B00A75B9A; + }; + 13B07F861A680F5B00A75B9A = { + LastSwiftMigration = 1120; + }; + }; + }; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "sampleNewArchitecture" */; + compatibilityVersion = "Xcode 12.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 83CBB9F61A601CBA00E9B192; + productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 13B07F861A680F5B00A75B9A /* sampleNewArchitecture */, + 00E356ED1AD99517003FC87E /* sampleNewArchitectureTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 00E356EC1AD99517003FC87E /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F8E1A680F5B00A75B9A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/.xcode.env.local", + "$(SRCROOT)/.xcode.env", + ); + name = "Bundle React Native code and images"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export SENTRY_PROPERTIES=sentry.properties\nexport EXTRA_PACKAGER_ARGS=\"--sourcemap-output $DERIVED_FILE_DIR/main.jsbundle.map\"\nset -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT \\\"../../node_modules/@sentry/cli/bin/sentry-cli react-native xcode $REACT_NATIVE_XCODE\\\"\"\n\nexport MODULES_PATHS=\"$PWD/../node_modules,$PWD/../../..\"\n/bin/sh ../../scripts/collect-modules.sh\n"; + }; + 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 8152B8B60F6641B996EA3E8F /* Upload Debug Symbols to Sentry */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Upload Debug Symbols to Sentry"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\nexport SENTRY_PROPERTIES=sentry.properties\n[[ $SENTRY_INCLUDE_NATIVE_SOURCES == \"true\" ]] && INCLUDE_SOURCES_FLAG=\"--include-sources\" || INCLUDE_SOURCES_FLAG=\"\"\n../../node_modules/@sentry/cli/bin/sentry-cli debug-files upload \"$INCLUDE_SOURCES_FLAG\"\n"; + }; + A55EABD7B0C7F3A422A6CC61 /* [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-sampleNewArchitecture-sampleNewArchitectureTests-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; + }; + C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-sampleNewArchitecture-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; + }; + C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture-sampleNewArchitectureTests/Pods-sampleNewArchitecture-sampleNewArchitectureTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture-sampleNewArchitectureTests/Pods-sampleNewArchitecture-sampleNewArchitectureTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture-sampleNewArchitectureTests/Pods-sampleNewArchitecture-sampleNewArchitectureTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture/Pods-sampleNewArchitecture-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture-sampleNewArchitectureTests/Pods-sampleNewArchitecture-sampleNewArchitectureTests-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture-sampleNewArchitectureTests/Pods-sampleNewArchitecture-sampleNewArchitectureTests-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-sampleNewArchitecture-sampleNewArchitectureTests/Pods-sampleNewArchitecture-sampleNewArchitectureTests-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + FD10A7F022414F080027D42C /* Start Packager */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Start Packager"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 00E356EA1AD99517003FC87E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 00E356F31AD99517003FC87E /* sampleNewArchitectureTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 13B07F871A680F5B00A75B9A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, + 13B07FC11A68108700A75B9A /* main.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 13B07F861A680F5B00A75B9A /* sampleNewArchitecture */; + targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 00E356F61AD99517003FC87E /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-sampleNewArchitecture-sampleNewArchitectureTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = sampleNewArchitectureTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sampleNewArchitecture.app/sampleNewArchitecture"; + }; + name = Debug; + }; + 00E356F71AD99517003FC87E /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-sampleNewArchitecture-sampleNewArchitectureTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + COPY_PHASE_STRIP = NO; + INFOPLIST_FILE = sampleNewArchitectureTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "-ObjC", + "-lc++", + "$(inherited)", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sampleNewArchitecture.app/sampleNewArchitecture"; + }; + name = Release; + }; + 13B07F941A680F5B00A75B9A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-sampleNewArchitecture.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = sampleNewArchitecture/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = sampleNewArchitecture; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 13B07F951A680F5B00A75B9A /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-sampleNewArchitecture.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = 1; + INFOPLIST_FILE = sampleNewArchitecture/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + OTHER_LDFLAGS = ( + "$(inherited)", + "-ObjC", + "-lc++", + ); + PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = sampleNewArchitecture; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; + 83CBBA201A601CBA00E9B192 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + SENTRY_INCLUDE_NATIVE_SOURCES = false; + }; + name = Debug; + }; + 83CBBA211A601CBA00E9B192 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; + LD_RUNPATH_SEARCH_PATHS = ( + /usr/lib/swift, + "$(inherited)", + ); + LIBRARY_SEARCH_PATHS = ( + "\"$(SDKROOT)/usr/lib/swift\"", + "\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"", + "\"$(inherited)\"", + ); + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CPLUSPLUSFLAGS = ( + "$(OTHER_CFLAGS)", + "-DFOLLY_NO_CONFIG", + "-DFOLLY_MOBILE=1", + "-DFOLLY_USE_LIBCPP=1", + ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; + SDKROOT = iphoneos; + SENTRY_INCLUDE_NATIVE_SOURCES = false; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "sampleNewArchitectureTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 00E356F61AD99517003FC87E /* Debug */, + 00E356F71AD99517003FC87E /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "sampleNewArchitecture" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 13B07F941A680F5B00A75B9A /* Debug */, + 13B07F951A680F5B00A75B9A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "sampleNewArchitecture" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 83CBBA201A601CBA00E9B192 /* Debug */, + 83CBBA211A601CBA00E9B192 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; +} diff --git a/sample-new-architecture/ios/sampleNewArchitecture.xcodeproj/xcshareddata/xcschemes/sampleNewArchitecture.xcscheme b/sample-new-architecture/ios/sampleNewArchitecture.xcodeproj/xcshareddata/xcschemes/sampleNewArchitecture.xcscheme new file mode 100644 index 000000000..6fc220076 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture.xcodeproj/xcshareddata/xcschemes/sampleNewArchitecture.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sample-new-architecture/ios/sampleNewArchitecture.xcworkspace/contents.xcworkspacedata b/sample-new-architecture/ios/sampleNewArchitecture.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..3f7d3abbd --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/sample-new-architecture/ios/sampleNewArchitecture.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/sample-new-architecture/ios/sampleNewArchitecture.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 000000000..18d981003 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.h b/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.h new file mode 100644 index 000000000..5d2808256 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.h @@ -0,0 +1,6 @@ +#import +#import + +@interface AppDelegate : RCTAppDelegate + +@end diff --git a/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.mm b/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.mm new file mode 100644 index 000000000..57d1bdd73 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.mm @@ -0,0 +1,53 @@ +#import "AppDelegate.h" + +#import +#import +#import +#import + +@interface AppDelegate () {} +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.moduleName = @"sampleNewArchitecture"; + // You can add your custom initial props in the dictionary below. + // They will be passed down to the ViewController used by React + self.initialProps = @{}; + + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ +#if DEBUG + return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; +#else + return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; +#endif +} + +/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off. +/// +/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html +/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture). +/// @return: `true` if the `concurrentRoot` feature is enabled. Otherwise, it returns `false`. +- (BOOL)concurrentRootEnabled +{ + return true; +} + +#pragma mark RCTTurboModuleManagerDelegate + +- (std::shared_ptr)getTurboModule:(const std::string &)name + jsInvoker:(std::shared_ptr)jsInvoker +{ + if (name == "NativeSampleModule") { + return std::make_shared(jsInvoker); + } + return nullptr; +} + +@end diff --git a/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/AppIcon.appiconset/Contents.json b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..81213230d --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,53 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/Contents.json b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/Contents.json new file mode 100644 index 000000000..2d92bd53f --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/sample-new-architecture/ios/sampleNewArchitecture/Info.plist b/sample-new-architecture/ios/sampleNewArchitecture/Info.plist new file mode 100644 index 000000000..e0fec8766 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/Info.plist @@ -0,0 +1,55 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + sampleNewArchitecture + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSExceptionDomains + + localhost + + NSExceptionAllowsInsecureHTTPLoads + + + + + NSLocationWhenInUseUsageDescription + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/sample-new-architecture/ios/sampleNewArchitecture/LaunchScreen.storyboard b/sample-new-architecture/ios/sampleNewArchitecture/LaunchScreen.storyboard new file mode 100644 index 000000000..0d7778254 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/LaunchScreen.storyboard @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sample-new-architecture/ios/sampleNewArchitecture/main.m b/sample-new-architecture/ios/sampleNewArchitecture/main.m new file mode 100644 index 000000000..d645c7246 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/main.m @@ -0,0 +1,10 @@ +#import + +#import "AppDelegate.h" + +int main(int argc, char *argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/sample-new-architecture/ios/sampleNewArchitectureTests/Info.plist b/sample-new-architecture/ios/sampleNewArchitectureTests/Info.plist new file mode 100644 index 000000000..ba72822e8 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitectureTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/sample-new-architecture/ios/sampleNewArchitectureTests/sampleNewArchitectureTests.m b/sample-new-architecture/ios/sampleNewArchitectureTests/sampleNewArchitectureTests.m new file mode 100644 index 000000000..bad9e2311 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitectureTests/sampleNewArchitectureTests.m @@ -0,0 +1,66 @@ +#import +#import + +#import +#import + +#define TIMEOUT_SECONDS 600 +#define TEXT_TO_LOOK_FOR @"Welcome to React" + +@interface sampleNewArchitectureTests : XCTestCase + +@end + +@implementation sampleNewArchitectureTests + +- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test +{ + if (test(view)) { + return YES; + } + for (UIView *subview in [view subviews]) { + if ([self findSubviewInView:subview matching:test]) { + return YES; + } + } + return NO; +} + +- (void)testRendersWelcomeScreen +{ + UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; + NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; + BOOL foundElement = NO; + + __block NSString *redboxError = nil; +#ifdef DEBUG + RCTSetLogFunction( + ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { + if (level >= RCTLogLevelError) { + redboxError = message; + } + }); +#endif + + while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { + [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; + + foundElement = [self findSubviewInView:vc.view + matching:^BOOL(UIView *view) { + if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { + return YES; + } + return NO; + }]; + } + +#ifdef DEBUG + RCTSetLogFunction(RCTDefaultLogFunction); +#endif + + XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); + XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); +} + +@end diff --git a/sample-new-architecture/ios/sentry.properties b/sample-new-architecture/ios/sentry.properties new file mode 100644 index 000000000..0cdf17015 --- /dev/null +++ b/sample-new-architecture/ios/sentry.properties @@ -0,0 +1,4 @@ +#defaults.url=https://sentry.io/ +defaults.org=sentry-sdks +defaults.project=sentry-react-native +#auth.token= diff --git a/sample-new-architecture/metro.config.js b/sample-new-architecture/metro.config.js new file mode 100644 index 000000000..facf38725 --- /dev/null +++ b/sample-new-architecture/metro.config.js @@ -0,0 +1,51 @@ +/** + * Metro configuration for React Native + * https://github.com/facebook/react-native + * + * @format + */ + +const path = require('path'); +const blacklist = require('metro-config/src/defaults/exclusionList'); + +const parentDir = path.resolve(__dirname, '..'); + +module.exports = { + projectRoot: __dirname, + watchFolders: [ + path.resolve(__dirname, 'node_modules'), + `${parentDir}/dist`, + `${parentDir}/node_modules`, + ], + resolver: { + blacklistRE: blacklist([ + new RegExp(`${parentDir}/node_modules/react-native/.*`), + ]), + extraNodeModules: new Proxy( + { + /* + As the parent dir node_modules is blacklisted as you can see above. So it won't be able + to find react-native to build the code from the parent folder, + so we'll have to redirect it to use the react-native inside sample's node_modules. + */ + 'react-native': path.resolve(__dirname, 'node_modules/react-native'), + }, + { + get: (target, name) => { + if (target.hasOwnProperty(name)) { + return target[name]; + } + return path.join(process.cwd(), `node_modules/${name}`); + }, + }, + ), + }, + transformer: { + getTransformOptions: async () => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: true, + }, + }), + }, +}; diff --git a/sample-new-architecture/mocks/fileMock.js b/sample-new-architecture/mocks/fileMock.js new file mode 100644 index 000000000..08d725cd4 --- /dev/null +++ b/sample-new-architecture/mocks/fileMock.js @@ -0,0 +1 @@ +export default ''; diff --git a/sample-new-architecture/package.json b/sample-new-architecture/package.json new file mode 100644 index 000000000..6bd8ef7ac --- /dev/null +++ b/sample-new-architecture/package.json @@ -0,0 +1,72 @@ +{ + "name": "sample-new-architecture", + "version": "0.0.1", + "private": true, + "scripts": { + "android": "react-native run-android", + "ios": "react-native run-ios", + "start": "react-native start", + "test": "jest", + "lint": "eslint . --ext .js,.jsx,.ts,.tsx", + "pod-install": "cd ios; RCT_NEW_ARCH_ENABLED=1 bundle exec pod install; cd ..", + "pod-install-production": "cd ios; PRODUCTION=1 RCT_NEW_ARCH_ENABLED=1 bundle exec pod install; cd ..", + "pod-install-legacy": "cd ios; bundle exec pod install; cd ..", + "pod-install-legacy-production": "cd ios; PRODUCTION=1 bundle exec pod install; cd .." + }, + "dependencies": { + "@react-native-community/cli-platform-android": "^10.1.3", + "@react-navigation/native": "^6.1.2", + "@react-navigation/stack": "^6.3.11", + "react": "18.2.0", + "react-native": "0.71.1", + "react-native-gesture-handler": "^2.9.0", + "react-native-safe-area-context": "^4.5.0", + "react-native-screens": "^3.19.0", + "react-redux": "^8.0.5", + "redux": "^4.2.0" + }, + "devDependencies": { + "@babel/core": "^7.20.0", + "@babel/preset-env": "^7.20.0", + "@babel/runtime": "^7.20.0", + "@react-native-community/eslint-config": "^3.0.0", + "@tsconfig/react-native": "^2.0.2", + "@types/jest": "^29.2.1", + "@types/react-test-renderer": "^18.0.0", + "@typescript-eslint/eslint-plugin": "^5.37.0", + "@typescript-eslint/parser": "^5.37.0", + "babel-jest": "^29.2.1", + "babel-plugin-module-resolver": "^5.0.0", + "eslint": "^8.19.0", + "eslint-plugin-ft-flow": "^2.0.3", + "eslint-plugin-jest": "^27.2.1", + "jest": "^29.2.1", + "metro-react-native-babel-preset": "^0.73.7", + "prettier": "^2.4.1", + "react-test-renderer": "18.2.0", + "typescript": "4.8.4" + }, + "jest": { + "preset": "react-native", + "moduleFileExtensions": [ + "ts", + "tsx", + "js", + "jsx", + "json", + "node" + ], + "moduleNameMapper": { + "\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/mocks/fileMock.js", + "\\.(css|less)$": "/mocks/fileMock.js" + } + }, + "codegenConfig": { + "name": "AppSpecs", + "type": "all", + "jsSrcsDir": "tm", + "android": { + "javaPackageName": "com.facebook.fbreact.specs" + } + } +} diff --git a/sample-new-architecture/react-native.config.js b/sample-new-architecture/react-native.config.js new file mode 100644 index 000000000..3cf8f35a7 --- /dev/null +++ b/sample-new-architecture/react-native.config.js @@ -0,0 +1,12 @@ +// Without this config the codegen fails +// because it can find @sentry/react-native +// in the dependencies +const path = require('path'); + +module.exports = { + dependencies: { + RNSentry: { + root: path.resolve(__dirname, '..'), + }, + }, +}; diff --git a/sample-new-architecture/src/App.tsx b/sample-new-architecture/src/App.tsx new file mode 100644 index 000000000..28d9ad60e --- /dev/null +++ b/sample-new-architecture/src/App.tsx @@ -0,0 +1,98 @@ +import React from 'react'; +import { + NavigationContainer, + NavigationContainerRef, +} from '@react-navigation/native'; +import { createStackNavigator } from '@react-navigation/stack'; + +// Import the Sentry React Native SDK +import * as Sentry from '@sentry/react-native'; + +import { SENTRY_INTERNAL_DSN } from './dsn'; +import HomeScreen from './Screens/HomeScreen'; +import TrackerScreen from './Screens/TrackerScreen'; +import ManualTrackerScreen from './Screens/ManualTrackerScreen'; +import PerformanceTimingScreen from './Screens/PerformanceTimingScreen'; +import ReduxScreen from './Screens/ReduxScreen'; +import { Provider } from 'react-redux'; +import { store } from './reduxApp'; + +const reactNavigationInstrumentation = + new Sentry.ReactNavigationInstrumentation({ + routeChangeTimeoutMs: 500, // How long it will wait for the route change to complete. Default is 1000ms + }); + +Sentry.init({ + // Replace the example DSN below with your own DSN: + dsn: SENTRY_INTERNAL_DSN, + debug: true, + beforeSend: (event, hint) => { + console.log('Event beforeSend:', event, 'hint:', hint); + return event; + }, + // This will be called with a boolean `didCallNativeInit` when the native SDK has been contacted. + onReady: ({ didCallNativeInit }) => { + console.log('onReady called with didCallNativeInit:', didCallNativeInit); + }, + integrations(integrations) { + integrations.push( + new Sentry.ReactNativeTracing({ + // The time to wait in ms until the transaction will be finished, For testing, default is 1000 ms + idleTimeout: 5000, + routingInstrumentation: reactNavigationInstrumentation, + tracingOrigins: ['localhost', /^\//, /^https:\/\//], + beforeNavigate: (context: Sentry.ReactNavigationTransactionContext) => { + // Example of not sending a transaction for the screen with the name "Manual Tracker" + if (context.data.route.name === 'ManualTracker') { + context.sampled = false; + } + + return context; + }, + }), + ); + return integrations.filter(i => i.name !== 'Dedupe'); + }, + enableAutoSessionTracking: true, + // For testing, session close when 5 seconds (instead of the default 30) in the background. + sessionTrackingIntervalMillis: 5000, + // This will capture ALL TRACES and likely use up all your quota + tracesSampleRate: 1.0, + attachStacktrace: true, + // Sets the `release` and `dist` on Sentry events. Make sure this matches EXACTLY with the values on your sourcemaps + // otherwise they will not work. + // release: 'myapp@1.2.3+1', + // dist: `1`, + attachViewHierarchy: true, +}); + +const Stack = createStackNavigator(); + +const App = () => { + const navigation = React.useRef>(null); + + return ( + + { + reactNavigationInstrumentation.registerNavigationContainer( + navigation, + ); + }}> + + + + + + + + + + ); +}; + +export default Sentry.wrap(App); diff --git a/sample-new-architecture/src/Screens/HomeScreen.tsx b/sample-new-architecture/src/Screens/HomeScreen.tsx new file mode 100644 index 000000000..930556697 --- /dev/null +++ b/sample-new-architecture/src/Screens/HomeScreen.tsx @@ -0,0 +1,217 @@ +import React from 'react'; +import { + StatusBar, + ScrollView, + Text, + Button as NativeButton, + View, + ButtonProps, + StyleSheet, +} from 'react-native'; + +import * as Sentry from '@sentry/react-native'; + +import { setScopeProperties } from '../setScopeProperties'; +import { StackNavigationProp } from '@react-navigation/stack'; +import { CommonActions } from '@react-navigation/native'; +import { UserFeedbackModal } from '../components/UserFeedbackModal'; +import { FallbackRender } from '@sentry/react'; +import NativeSampleModule from '../../tm/NativeSampleModule'; + +interface Props { + navigation: StackNavigationProp; +} + +const HomeScreen = (props: Props) => { + // Show bad code inside error boundary to trigger it. + const [showBadCode, setShowBadCode] = React.useState(false); + const [isFeedbackVisible, setFeedbackVisible] = React.useState(false); + + const onPressPerformanceTiming = () => { + // Navigate with a reset action just to test + props.navigation.dispatch( + CommonActions.reset({ + index: 1, + routes: [ + { name: 'Home' }, + { + name: 'PerformanceTiming', + params: { someParam: 'hello' }, + }, + ], + }), + ); + }; + + const errorBoundaryFallback: FallbackRender = ({ eventId }) => ( + Error boundary caught with event id: {eventId} + ); + + return ( + <> + + + Hey there! +