diff --git a/sample-new-architecture/.ruby-version b/sample-new-architecture/.ruby-version new file mode 100644 index 0000000000..49cdd668e1 --- /dev/null +++ b/sample-new-architecture/.ruby-version @@ -0,0 +1 @@ +2.7.6 diff --git a/sample-new-architecture/Gemfile.lock b/sample-new-architecture/Gemfile.lock index 51bf55aa63..c517153c14 100644 --- a/sample-new-architecture/Gemfile.lock +++ b/sample-new-architecture/Gemfile.lock @@ -89,9 +89,10 @@ GEM PLATFORMS arm64-darwin-21 + ruby DEPENDENCIES - cocoapods (~> 1.11, >= 1.11.2) + cocoapods (~> 1.11, >= 1.11.3) RUBY VERSION ruby 2.7.6p219 diff --git a/sample-new-architecture/android/app/build.gradle b/sample-new-architecture/android/app/build.gradle index 0b37d64a8e..d04633ef00 100644 --- a/sample-new-architecture/android/app/build.gradle +++ b/sample-new-architecture/android/app/build.gradle @@ -173,10 +173,12 @@ dependencies { 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" - } +if (newArchEnabled.toBoolean()) { + android { + externalNativeBuild { + cmake { + path "src/main/jni/CMakeLists.txt" + } + } } } diff --git a/sample-new-architecture/android/app/src/main/assets/logo_mini.png b/sample-new-architecture/android/app/src/main/assets/logo_mini.png new file mode 100644 index 0000000000..a7c02bbb61 Binary files /dev/null and b/sample-new-architecture/android/app/src/main/assets/logo_mini.png differ diff --git a/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/AssetsModule.java b/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/AssetsModule.java new file mode 100644 index 0000000000..27a2568d5b --- /dev/null +++ b/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/AssetsModule.java @@ -0,0 +1,42 @@ +package com.samplenewarchitecture; +import android.content.Context; + +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.WritableArray; +import com.facebook.react.bridge.WritableNativeArray; + +import java.io.InputStream; + +public class AssetsModule extends ReactContextBaseJavaModule { + + AssetsModule(ReactApplicationContext context) { + super(context); + } + + @Override + public String getName() { + return "AssetsModule"; + } + + @ReactMethod + public void getExampleAssetData(Promise promise) { + try { + InputStream stream = this.getReactApplicationContext().getResources().getAssets() + .open("logo_mini.png"); + int size = stream.available(); + byte[] buffer = new byte[size]; + stream.read(buffer); + stream.close(); + WritableArray array = new WritableNativeArray(); + for (int i = 0; i < size; i++) { + array.pushInt(buffer[i]); + } + promise.resolve(array); + } catch (Exception e) { + promise.reject(e); + } + } +} 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 index 8e772e3ba5..cae11eb38a 100644 --- 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 @@ -25,6 +25,7 @@ public boolean getUseDeveloperSupport() { protected List getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); + packages.add(new SamplePackage()); // Packages that cannot be autolinked yet can be added manually here, for example: // packages.add(new MyReactNativePackage()); for (ReactPackage pkg : packages) { diff --git a/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/SamplePackage.java b/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/SamplePackage.java new file mode 100644 index 0000000000..40a3751d6c --- /dev/null +++ b/sample-new-architecture/android/app/src/main/java/com/samplenewarchitecture/SamplePackage.java @@ -0,0 +1,28 @@ +package com.samplenewarchitecture; +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class SamplePackage implements ReactPackage { + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createNativeModules( + ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + + modules.add(new AssetsModule(reactContext)); + + return modules; + } + +} diff --git a/sample-new-architecture/ios/.xcode.env b/sample-new-architecture/ios/.xcode.env new file mode 100644 index 0000000000..772b339b4c --- /dev/null +++ b/sample-new-architecture/ios/.xcode.env @@ -0,0 +1 @@ +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 index d3b74b265f..a2933be324 100644 --- a/sample-new-architecture/ios/sampleNewArchitecture.xcodeproj/project.pbxproj +++ b/sample-new-architecture/ios/sampleNewArchitecture.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ 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 */; }; + 33E2D62A29A7719600B5042B /* RCTAssetsModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 33E2D62829A7719600B5042B /* RCTAssetsModule.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 */ @@ -37,6 +38,8 @@ 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; }; + 33E2D62829A7719600B5042B /* RCTAssetsModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RCTAssetsModule.m; path = sampleNewArchitecture/RCTAssetsModule.m; sourceTree = ""; }; + 33E2D62929A7719600B5042B /* RCTAssetsModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RCTAssetsModule.h; path = sampleNewArchitecture/RCTAssetsModule.h; sourceTree = ""; }; 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 = ""; }; @@ -86,6 +89,8 @@ 13B07FAE1A68108700A75B9A /* sampleNewArchitecture */ = { isa = PBXGroup; children = ( + 33E2D62929A7719600B5042B /* RCTAssetsModule.h */, + 33E2D62829A7719600B5042B /* RCTAssetsModule.m */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.mm */, 13B07FB51A68108700A75B9A /* Images.xcassets */, @@ -429,6 +434,7 @@ files = ( 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, + 33E2D62A29A7719600B5042B /* RCTAssetsModule.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -514,6 +520,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = sampleNewArchitecture; + RCT_NEW_ARCH_ENABLED = 1; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -539,6 +546,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = sampleNewArchitecture; + RCT_NEW_ARCH_ENABLED = 1; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; diff --git a/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.mm b/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.mm index 57d1bdd738..58124ed5c0 100644 --- a/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.mm +++ b/sample-new-architecture/ios/sampleNewArchitecture/AppDelegate.mm @@ -3,7 +3,10 @@ #import #import #import + +#ifdef RCT_NEW_ARCH_ENABLED #import +#endif @interface AppDelegate () {} @end @@ -44,9 +47,11 @@ - (BOOL)concurrentRootEnabled - (std::shared_ptr)getTurboModule:(const std::string &)name jsInvoker:(std::shared_ptr)jsInvoker { +#ifdef RCT_NEW_ARCH_ENABLED if (name == "NativeSampleModule") { return std::make_shared(jsInvoker); } +#endif return nullptr; } diff --git a/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/Contents.json b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/Contents.json index 2d92bd53fd..73c00596a7 100644 --- a/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/Contents.json +++ b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } } diff --git a/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/ExampleBinaryData.dataset/Contents.json b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/ExampleBinaryData.dataset/Contents.json new file mode 100644 index 0000000000..b5e65a72f3 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/ExampleBinaryData.dataset/Contents.json @@ -0,0 +1,13 @@ +{ + "data" : [ + { + "filename" : "logo_mini.png", + "idiom" : "universal", + "universal-type-identifier" : "image\/png" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/ExampleBinaryData.dataset/logo_mini.png b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/ExampleBinaryData.dataset/logo_mini.png new file mode 100644 index 0000000000..a7c02bbb61 Binary files /dev/null and b/sample-new-architecture/ios/sampleNewArchitecture/Images.xcassets/ExampleBinaryData.dataset/logo_mini.png differ diff --git a/sample-new-architecture/ios/sampleNewArchitecture/RCTAssetsModule.h b/sample-new-architecture/ios/sampleNewArchitecture/RCTAssetsModule.h new file mode 100644 index 0000000000..0cde90cb2d --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/RCTAssetsModule.h @@ -0,0 +1,3 @@ +#import +@interface RCTAssetsModule : NSObject +@end diff --git a/sample-new-architecture/ios/sampleNewArchitecture/RCTAssetsModule.m b/sample-new-architecture/ios/sampleNewArchitecture/RCTAssetsModule.m new file mode 100644 index 0000000000..dc9fd70635 --- /dev/null +++ b/sample-new-architecture/ios/sampleNewArchitecture/RCTAssetsModule.m @@ -0,0 +1,28 @@ +#import "RCTAssetsModule.h" + +@implementation RCTAssetsModule + +RCT_EXPORT_METHOD(getExampleAssetData: (RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject) +{ + NSDataAsset *data = [[NSDataAsset alloc] initWithName:@"ExampleBinaryData"]; + if (data == nil) { + reject(@"SampleSentryReactNative",@"Failed to load exmaple binary data asset.", nil); + } + + NSMutableArray *array = [NSMutableArray arrayWithCapacity:data.data.length]; + + const char *bytes = [data.data bytes]; + + for (int i = 0; i < [data.data length]; i++) + { + [array addObject:[[NSNumber alloc] initWithChar:bytes[i]]]; + } + + resolve(array); +} + +RCT_EXPORT_MODULE(AssetsModule); + +@end + diff --git a/sample-new-architecture/src/App.tsx b/sample-new-architecture/src/App.tsx index 28d9ad60e7..9001c73ad3 100644 --- a/sample-new-architecture/src/App.tsx +++ b/sample-new-architecture/src/App.tsx @@ -26,8 +26,8 @@ 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); + beforeSend: (event: Sentry.Event) => { + console.log('Event beforeSend:', event); return event; }, // This will be called with a boolean `didCallNativeInit` when the native SDK has been contacted. @@ -59,11 +59,14 @@ Sentry.init({ // This will capture ALL TRACES and likely use up all your quota tracesSampleRate: 1.0, attachStacktrace: true, + // Attach screenshots to events. + attachScreenshot: true, + // Attach view hierarchy to events. + attachViewHierarchy: 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(); diff --git a/sample-new-architecture/src/Screens/HomeScreen.tsx b/sample-new-architecture/src/Screens/HomeScreen.tsx index 930556697b..4f370947e8 100644 --- a/sample-new-architecture/src/Screens/HomeScreen.tsx +++ b/sample-new-architecture/src/Screens/HomeScreen.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { StatusBar, ScrollView, @@ -7,6 +7,7 @@ import { View, ButtonProps, StyleSheet, + NativeModules, } from 'react-native'; import * as Sentry from '@sentry/react-native'; @@ -18,6 +19,8 @@ import { UserFeedbackModal } from '../components/UserFeedbackModal'; import { FallbackRender } from '@sentry/react'; import NativeSampleModule from '../../tm/NativeSampleModule'; +const { AssetsModule } = NativeModules; + interface Props { navigation: StackNavigationProp; } @@ -47,6 +50,13 @@ const HomeScreen = (props: Props) => { Error boundary caught with event id: {eventId} ); + const [data, setData] = React.useState(null); + useEffect(() => { + AssetsModule.getExampleAssetData().then((asset: number[]) => + setData(new Uint8Array(asset)), + ); + }, []); + return ( <> @@ -105,7 +115,7 @@ const HomeScreen = (props: Props) => {