@sentry/react-native 6.7.0 → 6.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/RNSentry.podspec +1 -1
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +35 -0
  4. package/android/src/main/java/io/sentry/react/RNSentryVersion.java +1 -1
  5. package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +5 -0
  6. package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +5 -0
  7. package/dist/js/NativeRNSentry.d.ts +1 -0
  8. package/dist/js/NativeRNSentry.d.ts.map +1 -1
  9. package/dist/js/NativeRNSentry.js.map +1 -1
  10. package/dist/js/feedback/FeedbackWidget.d.ts +25 -0
  11. package/dist/js/feedback/FeedbackWidget.d.ts.map +1 -0
  12. package/dist/js/feedback/FeedbackWidget.js +249 -0
  13. package/dist/js/feedback/FeedbackWidget.js.map +1 -0
  14. package/dist/js/feedback/FeedbackWidget.styles.d.ts +8 -0
  15. package/dist/js/feedback/FeedbackWidget.styles.d.ts.map +1 -0
  16. package/dist/js/feedback/FeedbackWidget.styles.js +120 -0
  17. package/dist/js/feedback/FeedbackWidget.styles.js.map +1 -0
  18. package/dist/js/feedback/FeedbackWidget.types.d.ts +218 -0
  19. package/dist/js/feedback/FeedbackWidget.types.d.ts.map +1 -0
  20. package/dist/js/feedback/FeedbackWidget.types.js +2 -0
  21. package/dist/js/feedback/FeedbackWidget.types.js.map +1 -0
  22. package/dist/js/feedback/FeedbackWidgetManager.d.ts +33 -0
  23. package/dist/js/feedback/FeedbackWidgetManager.d.ts.map +1 -0
  24. package/dist/js/feedback/FeedbackWidgetManager.js +188 -0
  25. package/dist/js/feedback/FeedbackWidgetManager.js.map +1 -0
  26. package/dist/js/feedback/branding.d.ts +5 -0
  27. package/dist/js/feedback/branding.d.ts.map +1 -0
  28. package/dist/js/feedback/branding.js +5 -0
  29. package/dist/js/feedback/branding.js.map +1 -0
  30. package/dist/js/feedback/defaults.d.ts +3 -0
  31. package/dist/js/feedback/defaults.d.ts.map +1 -0
  32. package/dist/js/feedback/defaults.js +72 -0
  33. package/dist/js/feedback/defaults.js.map +1 -0
  34. package/dist/js/feedback/integration.d.ts +10 -0
  35. package/dist/js/feedback/integration.d.ts.map +1 -0
  36. package/dist/js/feedback/integration.js +17 -0
  37. package/dist/js/feedback/integration.js.map +1 -0
  38. package/dist/js/feedback/lazy.d.ts +10 -0
  39. package/dist/js/feedback/lazy.d.ts.map +1 -0
  40. package/dist/js/feedback/lazy.js +26 -0
  41. package/dist/js/feedback/lazy.js.map +1 -0
  42. package/dist/js/feedback/utils.d.ts +17 -0
  43. package/dist/js/feedback/utils.d.ts.map +1 -0
  44. package/dist/js/feedback/utils.js +38 -0
  45. package/dist/js/feedback/utils.js.map +1 -0
  46. package/dist/js/index.d.ts +2 -0
  47. package/dist/js/index.d.ts.map +1 -1
  48. package/dist/js/index.js +2 -0
  49. package/dist/js/index.js.map +1 -1
  50. package/dist/js/integrations/debugsymbolicator.js +9 -1
  51. package/dist/js/integrations/debugsymbolicator.js.map +1 -1
  52. package/dist/js/integrations/debugsymbolicatorutils.js +9 -1
  53. package/dist/js/integrations/debugsymbolicatorutils.js.map +1 -1
  54. package/dist/js/integrations/devicecontext.js +9 -1
  55. package/dist/js/integrations/devicecontext.js.map +1 -1
  56. package/dist/js/integrations/exports.d.ts +1 -0
  57. package/dist/js/integrations/exports.d.ts.map +1 -1
  58. package/dist/js/integrations/exports.js +1 -0
  59. package/dist/js/integrations/exports.js.map +1 -1
  60. package/dist/js/integrations/modulesloader.js +9 -1
  61. package/dist/js/integrations/modulesloader.js.map +1 -1
  62. package/dist/js/integrations/reactnativeerrorhandlers.js +9 -1
  63. package/dist/js/integrations/reactnativeerrorhandlers.js.map +1 -1
  64. package/dist/js/integrations/release.js +9 -1
  65. package/dist/js/integrations/release.js.map +1 -1
  66. package/dist/js/integrations/screenshot.js +9 -1
  67. package/dist/js/integrations/screenshot.js.map +1 -1
  68. package/dist/js/integrations/sdkinfo.js +9 -1
  69. package/dist/js/integrations/sdkinfo.js.map +1 -1
  70. package/dist/js/integrations/viewhierarchy.js +9 -1
  71. package/dist/js/integrations/viewhierarchy.js.map +1 -1
  72. package/dist/js/replay/mobilereplay.js +9 -1
  73. package/dist/js/replay/mobilereplay.js.map +1 -1
  74. package/dist/js/sdk.d.ts.map +1 -1
  75. package/dist/js/sdk.js +12 -2
  76. package/dist/js/sdk.js.map +1 -1
  77. package/dist/js/tools/metroMiddleware.js +11 -3
  78. package/dist/js/tools/metroMiddleware.js.map +1 -1
  79. package/dist/js/tools/metroconfig.js +15 -2
  80. package/dist/js/tools/metroconfig.js.map +1 -1
  81. package/dist/js/tools/sentryMetroSerializer.js +11 -3
  82. package/dist/js/tools/sentryMetroSerializer.js.map +1 -1
  83. package/dist/js/tracing/integrations/appStart.js +9 -1
  84. package/dist/js/tracing/integrations/appStart.js.map +1 -1
  85. package/dist/js/tracing/integrations/nativeFrames.js +9 -1
  86. package/dist/js/tracing/integrations/nativeFrames.js.map +1 -1
  87. package/dist/js/utils/worldwide.d.ts +1 -0
  88. package/dist/js/utils/worldwide.d.ts.map +1 -1
  89. package/dist/js/utils/worldwide.js.map +1 -1
  90. package/dist/js/version.d.ts +1 -1
  91. package/dist/js/version.js +1 -1
  92. package/dist/js/version.js.map +1 -1
  93. package/dist/js/wrapper.d.ts +1 -0
  94. package/dist/js/wrapper.d.ts.map +1 -1
  95. package/dist/js/wrapper.js +35 -1
  96. package/dist/js/wrapper.js.map +1 -1
  97. package/ios/RNSentry.mm +70 -17
  98. package/ios/RNSentryVersion.m +1 -1
  99. package/package.json +6 -6
  100. package/plugin/build/withSentry.d.ts +2 -0
  101. package/plugin/build/withSentry.js +10 -0
  102. package/plugin/build/withSentryAndroidGradlePlugin.d.ts +15 -0
  103. package/plugin/build/withSentryAndroidGradlePlugin.js +91 -0
  104. package/scripts/collect-modules.sh +5 -5
  105. package/src/js/NativeRNSentry.ts +1 -0
  106. package/ts3.8/dist/js/NativeRNSentry.d.ts +1 -0
  107. package/ts3.8/dist/js/feedback/FeedbackWidget.d.ts +25 -0
  108. package/ts3.8/dist/js/feedback/FeedbackWidget.styles.d.ts +8 -0
  109. package/ts3.8/dist/js/feedback/FeedbackWidget.types.d.ts +218 -0
  110. package/ts3.8/dist/js/feedback/FeedbackWidgetManager.d.ts +33 -0
  111. package/ts3.8/dist/js/feedback/branding.d.ts +5 -0
  112. package/ts3.8/dist/js/feedback/defaults.d.ts +3 -0
  113. package/ts3.8/dist/js/feedback/integration.d.ts +10 -0
  114. package/ts3.8/dist/js/feedback/lazy.d.ts +10 -0
  115. package/ts3.8/dist/js/feedback/utils.d.ts +17 -0
  116. package/ts3.8/dist/js/index.d.ts +2 -0
  117. package/ts3.8/dist/js/integrations/exports.d.ts +1 -0
  118. package/ts3.8/dist/js/utils/worldwide.d.ts +1 -0
  119. package/ts3.8/dist/js/version.d.ts +1 -1
  120. package/ts3.8/dist/js/wrapper.d.ts +1 -0
package/ios/RNSentry.mm CHANGED
@@ -641,26 +641,50 @@ RCT_EXPORT_METHOD(fetchViewHierarchy
641
641
  RCT_EXPORT_METHOD(setUser : (NSDictionary *)userKeys otherUserKeys : (NSDictionary *)userDataKeys)
642
642
  {
643
643
  [SentrySDK configureScope:^(SentryScope *_Nonnull scope) {
644
- if (nil == userKeys && nil == userDataKeys) {
645
- [scope setUser:nil];
646
- } else {
647
- SentryUser *userInstance = [[SentryUser alloc] init];
648
-
649
- if (nil != userKeys) {
650
- [userInstance setUserId:userKeys[@"id"]];
651
- [userInstance setIpAddress:userKeys[@"ip_address"]];
652
- [userInstance setEmail:userKeys[@"email"]];
653
- [userInstance setUsername:userKeys[@"username"]];
654
- [userInstance setSegment:userKeys[@"segment"]];
655
- }
644
+ [scope setUser:[RNSentry userFrom:userKeys otherUserKeys:userDataKeys]];
645
+ }];
646
+ }
656
647
 
657
- if (nil != userDataKeys) {
658
- [userInstance setData:userDataKeys];
659
- }
648
+ + (SentryUser *_Nullable)userFrom:(NSDictionary *)userKeys
649
+ otherUserKeys:(NSDictionary *)userDataKeys
650
+ {
651
+ // we can safely ignore userDataKeys since if original JS user was null userKeys will be null
652
+ if ([userKeys isKindOfClass:NSDictionary.class]) {
653
+ SentryUser *userInstance = [[SentryUser alloc] init];
660
654
 
661
- [scope setUser:userInstance];
655
+ id userId = [userKeys valueForKey:@"id"];
656
+ if ([userId isKindOfClass:NSString.class]) {
657
+ [userInstance setUserId:userId];
662
658
  }
663
- }];
659
+ id ipAddress = [userKeys valueForKey:@"ip_address"];
660
+ if ([ipAddress isKindOfClass:NSString.class]) {
661
+ [userInstance setIpAddress:ipAddress];
662
+ }
663
+ id email = [userKeys valueForKey:@"email"];
664
+ if ([email isKindOfClass:NSString.class]) {
665
+ [userInstance setEmail:email];
666
+ }
667
+ id username = [userKeys valueForKey:@"username"];
668
+ if ([username isKindOfClass:NSString.class]) {
669
+ [userInstance setUsername:username];
670
+ }
671
+ id segment = [userKeys valueForKey:@"segment"];
672
+ if ([segment isKindOfClass:NSString.class]) {
673
+ [userInstance setSegment:segment];
674
+ }
675
+
676
+ if ([userDataKeys isKindOfClass:NSDictionary.class]) {
677
+ [userInstance setData:userDataKeys];
678
+ }
679
+
680
+ return userInstance;
681
+ }
682
+
683
+ if (![[NSNull null] isEqual:userKeys] && nil != userKeys) {
684
+ NSLog(@"[RNSentry] Method setUser received unexpected type of userKeys.");
685
+ }
686
+
687
+ return nil;
664
688
  }
665
689
 
666
690
  RCT_EXPORT_METHOD(addBreadcrumb : (NSDictionary *)breadcrumb)
@@ -745,6 +769,35 @@ RCT_EXPORT_METHOD(captureReplay
745
769
  #endif
746
770
  }
747
771
 
772
+ RCT_EXPORT_METHOD(getDataFromUri
773
+ : (NSString *_Nonnull)uri resolve
774
+ : (RCTPromiseResolveBlock)resolve rejecter
775
+ : (RCTPromiseRejectBlock)reject)
776
+ {
777
+ #if TARGET_OS_IPHONE || TARGET_OS_MACCATALYST
778
+ NSURL *fileURL = [NSURL URLWithString:uri];
779
+ if (![fileURL isFileURL]) {
780
+ reject(@"SentryReactNative", @"The provided URI is not a valid file:// URL", nil);
781
+ return;
782
+ }
783
+ NSError *error = nil;
784
+ NSData *fileData = [NSData dataWithContentsOfURL:fileURL options:0 error:&error];
785
+ if (error || !fileData) {
786
+ reject(@"SentryReactNative", @"Failed to read file data", error);
787
+ return;
788
+ }
789
+ NSMutableArray *byteArray = [NSMutableArray arrayWithCapacity:fileData.length];
790
+ const unsigned char *bytes = (const unsigned char *)fileData.bytes;
791
+
792
+ for (NSUInteger i = 0; i < fileData.length; i++) {
793
+ [byteArray addObject:@(bytes[i])];
794
+ }
795
+ resolve(byteArray);
796
+ #else
797
+ resolve(nil);
798
+ #endif
799
+ }
800
+
748
801
  RCT_EXPORT_SYNCHRONOUS_TYPED_METHOD(NSString *, getCurrentReplayId)
749
802
  {
750
803
  #if SENTRY_TARGET_REPLAY_SUPPORTED
@@ -3,4 +3,4 @@
3
3
  NSString *const NATIVE_SDK_NAME = @"sentry.cocoa.react-native";
4
4
  NSString *const REACT_NATIVE_SDK_NAME = @"sentry.javascript.react-native";
5
5
  NSString *const REACT_NATIVE_SDK_PACKAGE_NAME = @"npm:@sentry/react-native";
6
- NSString *const REACT_NATIVE_SDK_PACKAGE_VERSION = @"6.7.0";
6
+ NSString *const REACT_NATIVE_SDK_PACKAGE_VERSION = @"6.9.0";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@sentry/react-native",
3
3
  "homepage": "https://github.com/getsentry/sentry-react-native",
4
4
  "repository": "https://github.com/getsentry/sentry-react-native",
5
- "version": "6.7.0",
5
+ "version": "6.9.0",
6
6
  "description": "Official Sentry SDK for react-native",
7
7
  "typings": "dist/js/index.d.ts",
8
8
  "types": "dist/js/index.d.ts",
@@ -65,9 +65,9 @@
65
65
  "react-native": ">=0.65.0"
66
66
  },
67
67
  "dependencies": {
68
- "@sentry/babel-plugin-component-annotate": "3.1.2",
68
+ "@sentry/babel-plugin-component-annotate": "3.2.0",
69
69
  "@sentry/browser": "8.54.0",
70
- "@sentry/cli": "2.41.1",
70
+ "@sentry/cli": "2.42.1",
71
71
  "@sentry/core": "8.54.0",
72
72
  "@sentry/react": "8.54.0",
73
73
  "@sentry/types": "8.54.0",
@@ -77,11 +77,11 @@
77
77
  "@babel/core": "^7.25.2",
78
78
  "@expo/metro-config": "0.19.5",
79
79
  "@mswjs/interceptors": "^0.25.15",
80
- "@react-native/babel-preset": "0.77.0",
80
+ "@react-native/babel-preset": "0.77.1",
81
81
  "@sentry-internal/eslint-config-sdk": "8.54.0",
82
82
  "@sentry-internal/eslint-plugin-sdk": "8.54.0",
83
83
  "@sentry-internal/typescript": "8.54.0",
84
- "@sentry/wizard": "3.40.0",
84
+ "@sentry/wizard": "3.42.1",
85
85
  "@testing-library/react-native": "^12.7.2",
86
86
  "@types/jest": "^29.5.13",
87
87
  "@types/node": "^20.9.3",
@@ -107,7 +107,7 @@
107
107
  "metro": "0.81.0",
108
108
  "prettier": "^2.0.5",
109
109
  "react": "18.3.1",
110
- "react-native": "0.77.0",
110
+ "react-native": "0.77.1",
111
111
  "react-test-renderer": "^18.3.1",
112
112
  "rimraf": "^4.1.1",
113
113
  "ts-jest": "^29.1.1",
@@ -1,9 +1,11 @@
1
1
  import type { ConfigPlugin } from 'expo/config-plugins';
2
+ import type { SentryAndroidGradlePluginOptions } from './withSentryAndroidGradlePlugin';
2
3
  interface PluginProps {
3
4
  organization?: string;
4
5
  project?: string;
5
6
  authToken?: string;
6
7
  url?: string;
8
+ experimental_android?: SentryAndroidGradlePluginOptions;
7
9
  }
8
10
  export declare function getSentryProperties(props: PluginProps | void): string | null;
9
11
  declare const withSentry: ConfigPlugin<void | PluginProps>;
@@ -4,6 +4,7 @@ exports.withSentry = exports.getSentryProperties = void 0;
4
4
  const config_plugins_1 = require("expo/config-plugins");
5
5
  const utils_1 = require("./utils");
6
6
  const withSentryAndroid_1 = require("./withSentryAndroid");
7
+ const withSentryAndroidGradlePlugin_1 = require("./withSentryAndroidGradlePlugin");
7
8
  const withSentryIOS_1 = require("./withSentryIOS");
8
9
  const withSentryPlugin = (config, props) => {
9
10
  const sentryProperties = getSentryProperties(props);
@@ -19,6 +20,15 @@ const withSentryPlugin = (config, props) => {
19
20
  catch (e) {
20
21
  (0, utils_1.warnOnce)(`There was a problem with configuring your native Android project: ${e}`);
21
22
  }
23
+ // if `enableAndroidGradlePlugin` is provided configure the Sentry Android Gradle Plugin
24
+ if (props?.experimental_android && props?.experimental_android?.enableAndroidGradlePlugin) {
25
+ try {
26
+ cfg = (0, withSentryAndroidGradlePlugin_1.withSentryAndroidGradlePlugin)(cfg, props.experimental_android);
27
+ }
28
+ catch (e) {
29
+ (0, utils_1.warnOnce)(`There was a problem with configuring Sentry Android Gradle Plugin: ${e}`);
30
+ }
31
+ }
22
32
  try {
23
33
  cfg = (0, withSentryIOS_1.withSentryIOS)(cfg, sentryProperties);
24
34
  }
@@ -0,0 +1,15 @@
1
+ export interface SentryAndroidGradlePluginOptions {
2
+ enableAndroidGradlePlugin?: boolean;
3
+ includeProguardMapping?: boolean;
4
+ dexguardEnabled?: boolean;
5
+ autoUploadNativeSymbols?: boolean;
6
+ autoUploadProguardMapping?: boolean;
7
+ uploadNativeSymbols?: boolean;
8
+ includeNativeSources?: boolean;
9
+ includeSourceContext?: boolean;
10
+ }
11
+ /**
12
+ * Adds the Sentry Android Gradle Plugin to the project.
13
+ * https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/#enable-sentry-agp
14
+ */
15
+ export declare function withSentryAndroidGradlePlugin(config: any, { includeProguardMapping, dexguardEnabled, autoUploadProguardMapping, uploadNativeSymbols, autoUploadNativeSymbols, includeNativeSources, includeSourceContext, }?: SentryAndroidGradlePluginOptions): any;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withSentryAndroidGradlePlugin = void 0;
4
+ const config_plugins_1 = require("@expo/config-plugins");
5
+ const utils_1 = require("./utils");
6
+ /**
7
+ * Adds the Sentry Android Gradle Plugin to the project.
8
+ * https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/#enable-sentry-agp
9
+ */
10
+ function withSentryAndroidGradlePlugin(config, { includeProguardMapping = true, dexguardEnabled = false, autoUploadProguardMapping = true, uploadNativeSymbols = true, autoUploadNativeSymbols = true, includeNativeSources = true, includeSourceContext = false, } = {}) {
11
+ const version = '4.14.1';
12
+ // Modify android/build.gradle
13
+ const withSentryProjectBuildGradle = (config) => {
14
+ return (0, config_plugins_1.withProjectBuildGradle)(config, (projectBuildGradle) => {
15
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
16
+ if (!projectBuildGradle.modResults || !projectBuildGradle.modResults.contents) {
17
+ (0, utils_1.warnOnce)('android/build.gradle content is missing or undefined.');
18
+ return config;
19
+ }
20
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
21
+ if (projectBuildGradle.modResults.language !== 'groovy') {
22
+ (0, utils_1.warnOnce)('Cannot configure Sentry in android/build.gradle because it is not in Groovy.');
23
+ return config;
24
+ }
25
+ const dependency = `classpath("io.sentry:sentry-android-gradle-plugin:${version}")`;
26
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
27
+ if (projectBuildGradle.modResults.contents.includes(dependency)) {
28
+ (0, utils_1.warnOnce)('sentry-android-gradle-plugin dependency in already in android/build.gradle.');
29
+ return config;
30
+ }
31
+ try {
32
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
33
+ const updatedContents = projectBuildGradle.modResults.contents.replace(/dependencies\s*{/, `dependencies {\n ${dependency}`);
34
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
35
+ if (updatedContents === projectBuildGradle.modResults.contents) {
36
+ (0, utils_1.warnOnce)('Failed to inject the dependency. Could not find `dependencies` in build.gradle.');
37
+ }
38
+ else {
39
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
40
+ projectBuildGradle.modResults.contents = updatedContents;
41
+ }
42
+ }
43
+ catch (error) {
44
+ (0, utils_1.warnOnce)(`An error occurred while trying to modify build.gradle`);
45
+ }
46
+ return projectBuildGradle;
47
+ });
48
+ };
49
+ // Modify android/app/build.gradle
50
+ const withSentryAppBuildGradle = (config) => {
51
+ return (0, config_plugins_1.withAppBuildGradle)(config, (config) => {
52
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
53
+ if (config.modResults.language !== 'groovy') {
54
+ (0, utils_1.warnOnce)('Cannot configure Sentry in android/app/build.gradle because it is not in Groovy.');
55
+ return config;
56
+ }
57
+ const sentryPlugin = `apply plugin: "io.sentry.android.gradle"`;
58
+ const sentryConfig = `
59
+ sentry {
60
+ autoUploadProguardMapping = ${autoUploadProguardMapping}
61
+ includeProguardMapping = ${includeProguardMapping}
62
+ dexguardEnabled = ${dexguardEnabled}
63
+ uploadNativeSymbols = ${uploadNativeSymbols}
64
+ autoUploadNativeSymbols = ${autoUploadNativeSymbols}
65
+ includeNativeSources = ${includeNativeSources}
66
+ includeSourceContext = ${includeSourceContext}
67
+ tracingInstrumentation {
68
+ enabled = false
69
+ }
70
+ autoInstallation {
71
+ enabled = false
72
+ }
73
+ }`;
74
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
75
+ let contents = config.modResults.contents;
76
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
77
+ if (!contents.includes(sentryPlugin)) {
78
+ contents = `${sentryPlugin}\n${contents}`;
79
+ }
80
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
81
+ if (!contents.includes('sentry {')) {
82
+ contents = `${contents}\n${sentryConfig}`;
83
+ }
84
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
85
+ config.modResults.contents = contents;
86
+ return config;
87
+ });
88
+ };
89
+ return withSentryAppBuildGradle(withSentryProjectBuildGradle(config));
90
+ }
91
+ exports.withSentryAndroidGradlePlugin = withSentryAndroidGradlePlugin;
@@ -28,7 +28,7 @@ if [[ -n "$NODE_BINARY" ]]; then
28
28
  nodePath="$NODE_BINARY"
29
29
  fi
30
30
 
31
- thisFilePath=$(dirname $0)
31
+ thisFilePath=$(dirname "$0")
32
32
  collectModulesScript="$thisFilePath/../dist/js/tools/collectModules.js"
33
33
 
34
34
  destination="$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH"
@@ -44,11 +44,11 @@ else
44
44
  modulesPaths="$MODULES_PATHS"
45
45
  fi
46
46
 
47
- type $nodePath >/dev/null 2>&1 || {
48
- echo >&2 "error: $nodePath not found! Modules won't be collected." \
47
+ if ! command -v "$nodePath" >/dev/null 2>&1; then
48
+ echo "[sentry/collect-modules.sh] $nodePath not found! Modules won't be collected." \
49
49
  "Please export NODE_BINARY in 'Build Phase' - 'Bundle React Native code and images'" \
50
50
  "to an absolute path of your node binary. Check your node path by 'which node'."
51
51
  exit 0 # Don't fail the build but inform about the problem
52
- }
52
+ fi
53
53
 
54
- $nodePath "$collectModulesScript" "$sourceMap" "$modulesOutput" "$modulesPaths"
54
+ "$nodePath" "$collectModulesScript" "$sourceMap" "$modulesOutput" "$modulesPaths"
@@ -48,6 +48,7 @@ export interface Spec extends TurboModule {
48
48
  captureReplay(isHardCrash: boolean): Promise<string | undefined | null>;
49
49
  getCurrentReplayId(): string | undefined | null;
50
50
  crashedLastRun(): Promise<boolean | undefined | null>;
51
+ getDataFromUri(uri: string): Promise<number[]>;
51
52
  }
52
53
 
53
54
  export type NativeStackFrame = {
@@ -43,6 +43,7 @@ export interface Spec extends TurboModule {
43
43
  captureReplay(isHardCrash: boolean): Promise<string | undefined | null>;
44
44
  getCurrentReplayId(): string | undefined | null;
45
45
  crashedLastRun(): Promise<boolean | undefined | null>;
46
+ getDataFromUri(uri: string): Promise<number[]>;
46
47
  }
47
48
  export type NativeStackFrame = {
48
49
  platform: string;
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+ import type { FeedbackWidgetProps, FeedbackWidgetState } from './FeedbackWidget.types';
3
+ /**
4
+ * @beta
5
+ * Implements a feedback form screen that sends feedback to Sentry using Sentry.captureFeedback.
6
+ */
7
+ export declare class FeedbackWidget extends React.Component<FeedbackWidgetProps, FeedbackWidgetState> {
8
+ static defaultProps: Partial<FeedbackWidgetProps>;
9
+ private static _savedState;
10
+ private _didSubmitForm;
11
+ constructor(props: FeedbackWidgetProps);
12
+ handleFeedbackSubmit: () => void;
13
+ onScreenshotButtonPress: () => void;
14
+ /**
15
+ * Save the state before unmounting the component.
16
+ */
17
+ componentWillUnmount(): void;
18
+ /**
19
+ * Renders the feedback form screen.
20
+ */
21
+ render(): React.ReactNode;
22
+ private _saveFormState;
23
+ private _clearFormState;
24
+ }
25
+ //# sourceMappingURL=FeedbackWidget.d.ts.map
@@ -0,0 +1,8 @@
1
+ import type { ViewStyle } from 'react-native';
2
+ import type { FeedbackWidgetStyles } from './FeedbackWidget.types';
3
+ declare const defaultStyles: FeedbackWidgetStyles;
4
+ export declare const modalWrapper: ViewStyle;
5
+ export declare const modalSheetContainer: ViewStyle;
6
+ export declare const topSpacer: ViewStyle;
7
+ export default defaultStyles;
8
+ //# sourceMappingURL=FeedbackWidget.styles.d.ts.map
@@ -0,0 +1,218 @@
1
+ import type { FeedbackFormData } from '@sentry/core';
2
+ import type { ImageStyle, TextStyle, ViewStyle } from 'react-native';
3
+ /**
4
+ * The props for the feedback form
5
+ */
6
+ export interface FeedbackWidgetProps extends FeedbackGeneralConfiguration, FeedbackTextConfiguration, FeedbackCallbacks, ImagePickerConfiguration {
7
+ styles?: FeedbackWidgetStyles;
8
+ }
9
+ /**
10
+ * General feedback configuration
11
+ */
12
+ export interface FeedbackGeneralConfiguration {
13
+ /**
14
+ * Show the Sentry branding
15
+ *
16
+ * @default true
17
+ */
18
+ showBranding?: boolean;
19
+ /**
20
+ * Should the email field be required?
21
+ */
22
+ isEmailRequired?: boolean;
23
+ /**
24
+ * Should the email field be validated?
25
+ */
26
+ shouldValidateEmail?: boolean;
27
+ /**
28
+ * Should the name field be required?
29
+ */
30
+ isNameRequired?: boolean;
31
+ /**
32
+ * Should the email input field be visible? Note: email will still be collected if set via `Sentry.setUser()`
33
+ */
34
+ showEmail?: boolean;
35
+ /**
36
+ * Should the name input field be visible? Note: name will still be collected if set via `Sentry.setUser()`
37
+ */
38
+ showName?: boolean;
39
+ /**
40
+ * This flag determines whether the "Add Screenshot" button is displayed
41
+ * @default false
42
+ */
43
+ enableScreenshot?: boolean;
44
+ /**
45
+ * Fill in email/name input fields with Sentry user context if it exists.
46
+ * The value of the email/name keys represent the properties of your user context.
47
+ */
48
+ useSentryUser?: {
49
+ email: string;
50
+ name: string;
51
+ };
52
+ }
53
+ /**
54
+ * All of the different text labels that can be customized
55
+ */
56
+ export interface FeedbackTextConfiguration {
57
+ /**
58
+ * The label for the Feedback form cancel button that closes dialog
59
+ */
60
+ cancelButtonLabel?: string;
61
+ /**
62
+ * The label for the Feedback form submit button that sends feedback
63
+ */
64
+ submitButtonLabel?: string;
65
+ /**
66
+ * The title of the Feedback form
67
+ */
68
+ formTitle?: string;
69
+ /**
70
+ * Label for the email input
71
+ */
72
+ emailLabel?: string;
73
+ /**
74
+ * Placeholder text for Feedback email input
75
+ */
76
+ emailPlaceholder?: string;
77
+ /**
78
+ * Label for the message input
79
+ */
80
+ messageLabel?: string;
81
+ /**
82
+ * Placeholder text for Feedback message input
83
+ */
84
+ messagePlaceholder?: string;
85
+ /**
86
+ * Label for the name input
87
+ */
88
+ nameLabel?: string;
89
+ /**
90
+ * Message after feedback was sent successfully
91
+ */
92
+ successMessageText?: string;
93
+ /**
94
+ * Placeholder text for Feedback name input
95
+ */
96
+ namePlaceholder?: string;
97
+ /**
98
+ * Text which indicates that a field is required
99
+ */
100
+ isRequiredLabel?: string;
101
+ /**
102
+ * The label for the button that adds a screenshot and renders the image editor
103
+ */
104
+ addScreenshotButtonLabel?: string;
105
+ /**
106
+ * The label for the button that removes a screenshot and hides the image editor
107
+ */
108
+ removeScreenshotButtonLabel?: string;
109
+ /**
110
+ * The title of the error dialog
111
+ */
112
+ errorTitle?: string;
113
+ /**
114
+ * The error message when the form is invalid
115
+ */
116
+ formError?: string;
117
+ /**
118
+ * The error message when the email is invalid
119
+ */
120
+ emailError?: string;
121
+ /**
122
+ * Message when there is a generic error
123
+ */
124
+ genericError?: string;
125
+ }
126
+ /**
127
+ * The public callbacks available for the feedback integration
128
+ */
129
+ export interface FeedbackCallbacks {
130
+ /**
131
+ * Callback when form is opened
132
+ */
133
+ onFormOpen?: () => void;
134
+ /**
135
+ * Callback when form is closed and not submitted
136
+ */
137
+ onFormClose?: () => void;
138
+ /**
139
+ * Callback when a screenshot is added
140
+ */
141
+ onAddScreenshot?: (addScreenshot: (uri: string) => void) => void;
142
+ /**
143
+ * Callback when feedback is successfully submitted
144
+ *
145
+ * After this you'll see a SuccessMessage on the screen for a moment.
146
+ */
147
+ onSubmitSuccess?: (data: FeedbackFormData) => void;
148
+ /**
149
+ * Callback when feedback is unsuccessfully submitted
150
+ */
151
+ onSubmitError?: (error: Error) => void;
152
+ /**
153
+ * Callback when the feedback form is submitted successfully, and the SuccessMessage is complete, or dismissed
154
+ */
155
+ onFormSubmitted?: () => void;
156
+ }
157
+ /**
158
+ * Image Picker configuration interface compatible with:
159
+ * - `react-native-image-picker`: 7.2, 8.0
160
+ * - `expo-image-picker`: 16.0`
161
+ */
162
+ export interface ImagePickerConfiguration {
163
+ imagePicker?: ImagePicker;
164
+ }
165
+ interface ImagePickerResponse {
166
+ assets?: ImagePickerAsset[];
167
+ }
168
+ interface ImagePickerAsset {
169
+ fileName?: string;
170
+ uri?: string;
171
+ base64?: string;
172
+ }
173
+ interface ExpoImageLibraryOptions {
174
+ mediaTypes?: 'images'[];
175
+ base64?: boolean;
176
+ }
177
+ interface ReactNativeImageLibraryOptions {
178
+ mediaType: 'photo';
179
+ includeBase64?: boolean;
180
+ }
181
+ export interface ImagePicker {
182
+ launchImageLibraryAsync?: (options?: ExpoImageLibraryOptions) => Promise<ImagePickerResponse>;
183
+ launchImageLibrary?: (options: ReactNativeImageLibraryOptions) => Promise<ImagePickerResponse>;
184
+ }
185
+ /**
186
+ * The styles for the feedback form
187
+ */
188
+ export interface FeedbackWidgetStyles {
189
+ container?: ViewStyle;
190
+ title?: TextStyle;
191
+ label?: TextStyle;
192
+ input?: TextStyle;
193
+ textArea?: TextStyle;
194
+ submitButton?: ViewStyle;
195
+ submitText?: TextStyle;
196
+ cancelButton?: ViewStyle;
197
+ cancelText?: TextStyle;
198
+ screenshotButton?: ViewStyle;
199
+ screenshotContainer?: ViewStyle;
200
+ screenshotThumbnail?: ImageStyle;
201
+ screenshotText?: TextStyle;
202
+ titleContainer?: ViewStyle;
203
+ sentryLogo?: ImageStyle;
204
+ }
205
+ /**
206
+ * The state of the feedback form
207
+ */
208
+ export interface FeedbackWidgetState {
209
+ isVisible: boolean;
210
+ name: string;
211
+ email: string;
212
+ description: string;
213
+ filename?: string;
214
+ attachment?: string | Uint8Array;
215
+ attachmentUri?: string;
216
+ }
217
+ export {};
218
+ //# sourceMappingURL=FeedbackWidget.types.d.ts.map
@@ -0,0 +1,33 @@
1
+ import * as React from 'react';
2
+ import { Animated } from 'react-native';
3
+ import type { FeedbackWidgetStyles } from './FeedbackWidget.types';
4
+ interface FeedbackWidgetProviderProps {
5
+ children: React.ReactNode;
6
+ styles?: FeedbackWidgetStyles;
7
+ }
8
+ interface FeedbackWidgetProviderState {
9
+ isVisible: boolean;
10
+ backgroundOpacity: Animated.Value;
11
+ panY: Animated.Value;
12
+ isScrollAtTop: boolean;
13
+ }
14
+ declare class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps> {
15
+ state: FeedbackWidgetProviderState;
16
+ private _panResponder;
17
+ constructor(props: FeedbackWidgetProviderProps);
18
+ /**
19
+ * Animates the background opacity when the modal is shown.
20
+ */
21
+ componentDidUpdate(_prevProps: any, prevState: FeedbackWidgetProviderState): void;
22
+ /**
23
+ * Renders the feedback form modal.
24
+ */
25
+ render(): React.ReactNode;
26
+ private _handleScroll;
27
+ private _setVisibilityFunction;
28
+ private _handleClose;
29
+ }
30
+ declare const showFeedbackWidget: () => void;
31
+ declare const resetFeedbackWidgetManager: () => void;
32
+ export { showFeedbackWidget, FeedbackWidgetProvider, resetFeedbackWidgetManager };
33
+ //# sourceMappingURL=FeedbackWidgetManager.d.ts.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Base64 encoded PNG image of the Sentry logo (source https://sentry.io/branding/)
3
+ */
4
+ export declare const sentryLogo = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAC4BAMAAABUVL5sAAAAD1BMVEUAAAA2Llo3LVk4LFg2LVmgcvrUAAAABHRSTlMAgL9ARyeO/QAAA7pJREFUeNrtWltynDAQFBIHIFUcgCQ6AIk5AAjd/0ypxFk3ouUCNJofl/rHy75a09MzI7Q2DQ0NDQ0NDQ0NDQ0N9eF+xPh9MKpwPv6FLss7R9yMImz8j8nowb9IglFDF6N+KCNIdqMFcGjpBbVUXdzHqKsXUhJGNb2g1vz6azRgX8XulUwMtVZjFsWkvFz10s0ooEO+9Vpxj/6rp9eI5VsdE6eJcDCxilqICiZWMHBSMkBVA2vq1SVrVyr6Ea5VMjHqjytTwcAgRVJ0DAy9VoWUTNT3tQysZGIYmGNTKHfK0q6oFkysYWCuHB0DaxX9yHLx5JKrhVC0TGwjWNRMvNAuW6PoR4TCepnqLLuiicEyKJq4g2C6Rc+hsInlgtHCF41OrD65INisObksbKy2/YJg9U08sGBTbRN3YaBQQu2i74/mcQil6vZr5C0dQpGbGKJvdOA1VDVxd5LHooPR5BJPdwql5vaLeq9FQZKJpa1kOoUSKpq45+m+ZK93aUpSwRyuafslUguCIZRZamKoBYQT80QmlqnF38p6bSIDcyg2q5fw/uo8dx0upZMLLdadQ1kgkNDEOOGiYYXjVKGJ8V00rEggcErurxAKCwQTi9RCAW7UFcUm5vPAOFNXFBY9DggQyp76jnIkOyBwaeqtyMScEu7w4JRNLnyQOjyvACcWpR145g6PV1fp9mvE0jMd3tWZXDR3/Ud2cSXZfmHhvNpEoFlgYsjFHX4AJc3kXXSTyEfDTrz94ptE1qvS9ouG1Ud2sQT5PVcHg3FL78FIYUpqxWK1yLzMxNzhHVaLzItMzB0eB/S4CDRHC+AzFTjhAiSSHx9tpgJXqnmhXi7VizM/F5v4V5oVqOIp81PpEW4Xt7PUA0kEe5WZ2PLt7ZopDg8Seue9GpxoU0WrHyFPgYlzmyrKPDxcpFeX3YRS5mGvxybmsC2tPhLJQxPzdsfliwMeLjAx9wcujoFIaEAX/KSYXz0s+9TE/E7LX0yF8lQvitl99sVjSgITl/yk6Lk48JjfGadnanHml8xjMvFTA+eL42CRwDKEZwbm4rBMyAmdH6UEz8HDTPj4d4ie1EJxJCQg56DXaxKOl0iGz0jcdebZluzhbFSA1yEZ2JzbHZKQe3I/EK4CErTHbwn84ZP+8Poxqrd/+I2cXJAw0v9VAkBiI3DhLryZEe6SXNeJk5HcHFu+Aom5wiIn2a7niZiE1WKMUhIOhNFJSQZzh0VG8tPcQufLSQI46sO9vcM0NDQ0NDQ0NDQ0NHxF/AFGJOBYBWrb5gAAAABJRU5ErkJggg==";
5
+ //# sourceMappingURL=branding.d.ts.map
@@ -0,0 +1,3 @@
1
+ import type { FeedbackWidgetProps } from './FeedbackWidget.types';
2
+ export declare const defaultConfiguration: Partial<FeedbackWidgetProps>;
3
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1,10 @@
1
+ import type { Integration } from '@sentry/core';
2
+ import type { FeedbackWidgetProps } from './FeedbackWidget.types';
3
+ export declare const MOBILE_FEEDBACK_INTEGRATION_NAME = "MobileFeedback";
4
+ type FeedbackIntegration = Integration & {
5
+ options: Partial<FeedbackWidgetProps>;
6
+ };
7
+ export declare const feedbackIntegration: (initOptions?: FeedbackWidgetProps) => FeedbackIntegration;
8
+ export declare const getFeedbackOptions: () => Partial<FeedbackWidgetProps>;
9
+ export {};
10
+ //# sourceMappingURL=integration.d.ts.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Lazy loads the feedback integration if it is not already loaded.
3
+ */
4
+ export declare function lazyLoadFeedbackIntegration(): void;
5
+ export declare const AUTO_INJECT_FEEDBACK_INTEGRATION_NAME = "AutoInjectMobileFeedback";
6
+ /**
7
+ * Lazy loads the auto inject feedback integration if it is not already loaded.
8
+ */
9
+ export declare function lazyLoadAutoInjectFeedbackIntegration(): void;
10
+ //# sourceMappingURL=lazy.d.ts.map