@sentry/react-native 7.0.0-alpha.0 → 7.0.0-beta.1
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.
- package/RNSentry.podspec +10 -3
- package/android/build.gradle +1 -1
- package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +16 -0
- package/android/src/main/java/io/sentry/react/RNSentryVersion.java +1 -1
- package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +5 -0
- package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +5 -0
- package/dist/js/NativeRNSentry.d.ts +1 -0
- package/dist/js/NativeRNSentry.d.ts.map +1 -1
- package/dist/js/NativeRNSentry.js.map +1 -1
- package/dist/js/client.d.ts +1 -0
- package/dist/js/client.d.ts.map +1 -1
- package/dist/js/client.js +16 -2
- package/dist/js/client.js.map +1 -1
- package/dist/js/feedback/FeedbackButton.d.ts +23 -0
- package/dist/js/feedback/FeedbackButton.d.ts.map +1 -0
- package/dist/js/feedback/FeedbackButton.js +51 -0
- package/dist/js/feedback/FeedbackButton.js.map +1 -0
- package/dist/js/feedback/FeedbackWidget.d.ts +14 -1
- package/dist/js/feedback/FeedbackWidget.d.ts.map +1 -1
- package/dist/js/feedback/FeedbackWidget.js +144 -48
- package/dist/js/feedback/FeedbackWidget.js.map +1 -1
- package/dist/js/feedback/FeedbackWidget.styles.d.ts +6 -3
- package/dist/js/feedback/FeedbackWidget.styles.d.ts.map +1 -1
- package/dist/js/feedback/FeedbackWidget.styles.js +155 -106
- package/dist/js/feedback/FeedbackWidget.styles.js.map +1 -1
- package/dist/js/feedback/FeedbackWidget.theme.d.ts +37 -0
- package/dist/js/feedback/FeedbackWidget.theme.d.ts.map +1 -0
- package/dist/js/feedback/FeedbackWidget.theme.js +31 -0
- package/dist/js/feedback/FeedbackWidget.theme.js.map +1 -0
- package/dist/js/feedback/FeedbackWidget.types.d.ts +71 -2
- package/dist/js/feedback/FeedbackWidget.types.d.ts.map +1 -1
- package/dist/js/feedback/FeedbackWidget.types.js.map +1 -1
- package/dist/js/feedback/FeedbackWidgetManager.d.ts +43 -23
- package/dist/js/feedback/FeedbackWidgetManager.d.ts.map +1 -1
- package/dist/js/feedback/FeedbackWidgetManager.js +62 -138
- package/dist/js/feedback/FeedbackWidgetManager.js.map +1 -1
- package/dist/js/feedback/FeedbackWidgetProvider.d.ts +48 -0
- package/dist/js/feedback/FeedbackWidgetProvider.d.ts.map +1 -0
- package/dist/js/feedback/FeedbackWidgetProvider.js +176 -0
- package/dist/js/feedback/FeedbackWidgetProvider.js.map +1 -0
- package/dist/js/feedback/ScreenshotButton.d.ts +25 -0
- package/dist/js/feedback/ScreenshotButton.d.ts.map +1 -0
- package/dist/js/feedback/ScreenshotButton.js +80 -0
- package/dist/js/feedback/ScreenshotButton.js.map +1 -0
- package/dist/js/feedback/defaults.d.ts +3 -1
- package/dist/js/feedback/defaults.d.ts.map +1 -1
- package/dist/js/feedback/defaults.js +15 -0
- package/dist/js/feedback/defaults.js.map +1 -1
- package/dist/js/feedback/icons.d.ts +30 -0
- package/dist/js/feedback/icons.d.ts.map +1 -0
- package/dist/js/feedback/icons.js +30 -0
- package/dist/js/feedback/icons.js.map +1 -0
- package/dist/js/feedback/integration.d.ts +19 -2
- package/dist/js/feedback/integration.d.ts.map +1 -1
- package/dist/js/feedback/integration.js +58 -3
- package/dist/js/feedback/integration.js.map +1 -1
- package/dist/js/feedback/lazy.d.ts +10 -0
- package/dist/js/feedback/lazy.d.ts.map +1 -1
- package/dist/js/feedback/lazy.js +24 -0
- package/dist/js/feedback/lazy.js.map +1 -1
- package/dist/js/feedback/utils.d.ts.map +1 -1
- package/dist/js/feedback/utils.js.map +1 -1
- package/dist/js/index.d.ts +5 -3
- package/dist/js/index.d.ts.map +1 -1
- package/dist/js/index.js +4 -2
- package/dist/js/index.js.map +1 -1
- package/dist/js/integrations/appRegistry.d.ts.map +1 -1
- package/dist/js/integrations/appRegistry.js.map +1 -1
- package/dist/js/integrations/breadcrumbs.d.ts +47 -0
- package/dist/js/integrations/breadcrumbs.d.ts.map +1 -0
- package/dist/js/integrations/breadcrumbs.js +15 -0
- package/dist/js/integrations/breadcrumbs.js.map +1 -0
- package/dist/js/integrations/debugsymbolicator.d.ts.map +1 -1
- package/dist/js/integrations/debugsymbolicator.js.map +1 -1
- package/dist/js/integrations/debugsymbolicatorutils.d.ts.map +1 -1
- package/dist/js/integrations/debugsymbolicatorutils.js.map +1 -1
- package/dist/js/integrations/default.d.ts.map +1 -1
- package/dist/js/integrations/default.js +2 -2
- package/dist/js/integrations/default.js.map +1 -1
- package/dist/js/integrations/devicecontext.d.ts.map +1 -1
- package/dist/js/integrations/devicecontext.js.map +1 -1
- package/dist/js/integrations/expocontext.d.ts.map +1 -1
- package/dist/js/integrations/expocontext.js.map +1 -1
- package/dist/js/integrations/exports.d.ts +2 -1
- package/dist/js/integrations/exports.d.ts.map +1 -1
- package/dist/js/integrations/exports.js +2 -1
- package/dist/js/integrations/exports.js.map +1 -1
- package/dist/js/integrations/modulesloader.d.ts.map +1 -1
- package/dist/js/integrations/modulesloader.js.map +1 -1
- package/dist/js/integrations/nativelinkederrors.d.ts.map +1 -1
- package/dist/js/integrations/nativelinkederrors.js.map +1 -1
- package/dist/js/integrations/reactnativeerrorhandlers.d.ts.map +1 -1
- package/dist/js/integrations/reactnativeerrorhandlers.js +65 -31
- package/dist/js/integrations/reactnativeerrorhandlers.js.map +1 -1
- package/dist/js/integrations/reactnativeerrorhandlersutils.d.ts.map +1 -1
- package/dist/js/integrations/reactnativeerrorhandlersutils.js.map +1 -1
- package/dist/js/integrations/reactnativeinfo.d.ts.map +1 -1
- package/dist/js/integrations/reactnativeinfo.js.map +1 -1
- package/dist/js/integrations/release.d.ts.map +1 -1
- package/dist/js/integrations/release.js.map +1 -1
- package/dist/js/integrations/rewriteframes.d.ts.map +1 -1
- package/dist/js/integrations/rewriteframes.js.map +1 -1
- package/dist/js/integrations/screenshot.d.ts.map +1 -1
- package/dist/js/integrations/screenshot.js.map +1 -1
- package/dist/js/integrations/sdkinfo.d.ts.map +1 -1
- package/dist/js/integrations/sdkinfo.js.map +1 -1
- package/dist/js/integrations/spotlight.d.ts.map +1 -1
- package/dist/js/integrations/spotlight.js.map +1 -1
- package/dist/js/integrations/viewhierarchy.d.ts.map +1 -1
- package/dist/js/integrations/viewhierarchy.js.map +1 -1
- package/dist/js/options.d.ts +4 -2
- package/dist/js/options.d.ts.map +1 -1
- package/dist/js/options.js +2 -3
- package/dist/js/options.js.map +1 -1
- package/dist/js/playground/animations.d.ts +4 -0
- package/dist/js/playground/animations.d.ts.map +1 -0
- package/dist/js/playground/animations.js +4 -0
- package/dist/js/playground/animations.js.map +1 -0
- package/dist/js/playground/examples.d.ts +13 -0
- package/dist/js/playground/examples.d.ts.map +1 -0
- package/dist/js/playground/examples.js +35 -0
- package/dist/js/playground/examples.js.map +1 -0
- package/dist/js/playground/images.d.ts +4 -0
- package/dist/js/playground/images.d.ts.map +1 -0
- package/dist/js/playground/images.js +4 -0
- package/dist/js/playground/images.js.map +1 -0
- package/dist/js/playground/index.d.ts +2 -0
- package/dist/js/playground/index.d.ts.map +1 -0
- package/dist/js/playground/index.js +2 -0
- package/dist/js/playground/index.js.map +1 -0
- package/dist/js/playground/modal.d.ts +29 -0
- package/dist/js/playground/modal.d.ts.map +1 -0
- package/dist/js/playground/modal.js +259 -0
- package/dist/js/playground/modal.js.map +1 -0
- package/dist/js/profiling/convertHermesProfile.d.ts.map +1 -1
- package/dist/js/profiling/convertHermesProfile.js.map +1 -1
- package/dist/js/profiling/debugid.d.ts.map +1 -1
- package/dist/js/profiling/debugid.js.map +1 -1
- package/dist/js/profiling/hermes.d.ts.map +1 -1
- package/dist/js/profiling/hermes.js.map +1 -1
- package/dist/js/profiling/integration.d.ts.map +1 -1
- package/dist/js/profiling/integration.js.map +1 -1
- package/dist/js/profiling/types.d.ts.map +1 -1
- package/dist/js/profiling/types.js.map +1 -1
- package/dist/js/profiling/utils.d.ts.map +1 -1
- package/dist/js/profiling/utils.js.map +1 -1
- package/dist/js/replay/CustomMask.d.ts.map +1 -1
- package/dist/js/replay/CustomMask.js.map +1 -1
- package/dist/js/replay/browserReplay.d.ts +13 -1
- package/dist/js/replay/browserReplay.d.ts.map +1 -1
- package/dist/js/replay/browserReplay.js +26 -0
- package/dist/js/replay/browserReplay.js.map +1 -1
- package/dist/js/replay/mobilereplay.d.ts +14 -1
- package/dist/js/replay/mobilereplay.d.ts.map +1 -1
- package/dist/js/replay/mobilereplay.js +9 -7
- package/dist/js/replay/mobilereplay.js.map +1 -1
- package/dist/js/replay/networkUtils.d.ts.map +1 -1
- package/dist/js/replay/networkUtils.js +4 -11
- package/dist/js/replay/networkUtils.js.map +1 -1
- package/dist/js/replay/replayInterface.d.ts +52 -0
- package/dist/js/replay/replayInterface.d.ts.map +1 -0
- package/dist/js/replay/replayInterface.js +2 -0
- package/dist/js/replay/replayInterface.js.map +1 -0
- package/dist/js/replay/xhrUtils.d.ts.map +1 -1
- package/dist/js/replay/xhrUtils.js.map +1 -1
- package/dist/js/scopeSync.d.ts.map +1 -1
- package/dist/js/scopeSync.js.map +1 -1
- package/dist/js/sdk.d.ts +1 -6
- package/dist/js/sdk.d.ts.map +1 -1
- package/dist/js/sdk.js +7 -19
- package/dist/js/sdk.js.map +1 -1
- package/dist/js/tools/collectModules.js.map +1 -1
- package/dist/js/tools/metroconfig.d.ts.map +1 -1
- package/dist/js/tools/metroconfig.js +1 -1
- package/dist/js/tools/metroconfig.js.map +1 -1
- package/dist/js/tools/sentryBabelTransformerUtils.d.ts.map +1 -1
- package/dist/js/tools/sentryBabelTransformerUtils.js +1 -1
- package/dist/js/tools/sentryBabelTransformerUtils.js.map +1 -1
- package/dist/js/tools/sentryMetroSerializer.d.ts.map +1 -1
- package/dist/js/tools/sentryMetroSerializer.js.map +1 -1
- package/dist/js/tools/vendor/metro/utils.d.ts.map +1 -1
- package/dist/js/tools/vendor/metro/utils.js.map +1 -1
- package/dist/js/touchevents.d.ts.map +1 -1
- package/dist/js/touchevents.js.map +1 -1
- package/dist/js/tracing/gesturetracing.d.ts.map +1 -1
- package/dist/js/tracing/gesturetracing.js.map +1 -1
- package/dist/js/tracing/integrations/appStart.d.ts +7 -1
- package/dist/js/tracing/integrations/appStart.d.ts.map +1 -1
- package/dist/js/tracing/integrations/appStart.js +61 -10
- package/dist/js/tracing/integrations/appStart.js.map +1 -1
- package/dist/js/tracing/integrations/nativeFrames.d.ts.map +1 -1
- package/dist/js/tracing/integrations/nativeFrames.js.map +1 -1
- package/dist/js/tracing/integrations/stalltracking.d.ts.map +1 -1
- package/dist/js/tracing/integrations/stalltracking.js.map +1 -1
- package/dist/js/tracing/integrations/timeToDisplayIntegration.d.ts.map +1 -1
- package/dist/js/tracing/integrations/timeToDisplayIntegration.js.map +1 -1
- package/dist/js/tracing/integrations/userInteraction.d.ts.map +1 -1
- package/dist/js/tracing/integrations/userInteraction.js.map +1 -1
- package/dist/js/tracing/onSpanEndUtils.d.ts.map +1 -1
- package/dist/js/tracing/onSpanEndUtils.js.map +1 -1
- package/dist/js/tracing/reactnativenavigation.d.ts.map +1 -1
- package/dist/js/tracing/reactnativenavigation.js.map +1 -1
- package/dist/js/tracing/reactnativeprofiler.d.ts.map +1 -1
- package/dist/js/tracing/reactnativeprofiler.js.map +1 -1
- package/dist/js/tracing/reactnativetracing.d.ts.map +1 -1
- package/dist/js/tracing/reactnativetracing.js.map +1 -1
- package/dist/js/tracing/reactnavigation.js.map +1 -1
- package/dist/js/tracing/span.d.ts.map +1 -1
- package/dist/js/tracing/span.js +5 -5
- package/dist/js/tracing/span.js.map +1 -1
- package/dist/js/tracing/timetodisplay.d.ts.map +1 -1
- package/dist/js/tracing/timetodisplay.js +13 -13
- package/dist/js/tracing/timetodisplay.js.map +1 -1
- package/dist/js/tracing/timetodisplaynative.d.ts.map +1 -1
- package/dist/js/tracing/timetodisplaynative.js.map +1 -1
- package/dist/js/tracing/utils.d.ts.map +1 -1
- package/dist/js/tracing/utils.js.map +1 -1
- package/dist/js/transports/encodePolyfill.d.ts +4 -0
- package/dist/js/transports/encodePolyfill.d.ts.map +1 -1
- package/dist/js/transports/encodePolyfill.js +19 -5
- package/dist/js/transports/encodePolyfill.js.map +1 -1
- package/dist/js/transports/native.d.ts.map +1 -1
- package/dist/js/transports/native.js.map +1 -1
- package/dist/js/utils/carrier.d.ts +5 -0
- package/dist/js/utils/carrier.d.ts.map +1 -0
- package/dist/js/utils/carrier.js +11 -0
- package/dist/js/utils/carrier.js.map +1 -0
- package/dist/js/utils/encode.d.ts +5 -0
- package/dist/js/utils/encode.d.ts.map +1 -0
- package/dist/js/utils/encode.js +13 -0
- package/dist/js/utils/encode.js.map +1 -0
- package/dist/js/utils/environment.d.ts.map +1 -1
- package/dist/js/utils/environment.js +3 -3
- package/dist/js/utils/environment.js.map +1 -1
- package/dist/js/utils/expoglobalobject.d.ts +2 -1
- package/dist/js/utils/expoglobalobject.d.ts.map +1 -1
- package/dist/js/utils/expoglobalobject.js.map +1 -1
- package/dist/js/utils/expomodules.d.ts +5 -1
- package/dist/js/utils/expomodules.d.ts.map +1 -1
- package/dist/js/utils/expomodules.js +7 -0
- package/dist/js/utils/expomodules.js.map +1 -1
- package/dist/js/utils/rnlibraries.d.ts.map +1 -1
- package/dist/js/utils/rnlibraries.js.map +1 -1
- package/dist/js/utils/safe.d.ts.map +1 -1
- package/dist/js/utils/safe.js.map +1 -1
- package/dist/js/utils/worldwide.d.ts +10 -2
- package/dist/js/utils/worldwide.d.ts.map +1 -1
- package/dist/js/utils/worldwide.js.map +1 -1
- package/dist/js/version.d.ts +1 -1
- package/dist/js/version.d.ts.map +1 -1
- package/dist/js/version.js +1 -1
- package/dist/js/version.js.map +1 -1
- package/dist/js/wrapper.d.ts +1 -0
- package/dist/js/wrapper.d.ts.map +1 -1
- package/dist/js/wrapper.js +25 -8
- package/dist/js/wrapper.js.map +1 -1
- package/ios/RNSentry.mm +24 -0
- package/ios/RNSentryOnDrawReporter.m +4 -0
- package/ios/RNSentryReplay.mm +1 -2
- package/ios/RNSentryVersion.m +1 -1
- package/package.json +13 -13
- package/plugin/build/withSentry.js +2 -2
- package/plugin/build/withSentryAndroidGradlePlugin.js +2 -2
- package/react-native.config.js +4 -4
- package/scripts/expo-upload-sourcemaps.js +2 -2
- package/scripts/sentry_utils.rb +5 -0
- package/src/js/NativeRNSentry.ts +1 -1
- package/ts3.8/dist/js/NativeRNSentry.d.ts +1 -0
- package/ts3.8/dist/js/client.d.ts +1 -0
- package/ts3.8/dist/js/feedback/FeedbackButton.d.ts +23 -0
- package/ts3.8/dist/js/feedback/FeedbackWidget.d.ts +14 -1
- package/ts3.8/dist/js/feedback/FeedbackWidget.styles.d.ts +6 -3
- package/ts3.8/dist/js/feedback/FeedbackWidget.theme.d.ts +37 -0
- package/ts3.8/dist/js/feedback/FeedbackWidget.types.d.ts +71 -2
- package/ts3.8/dist/js/feedback/FeedbackWidgetManager.d.ts +43 -23
- package/ts3.8/dist/js/feedback/FeedbackWidgetProvider.d.ts +48 -0
- package/ts3.8/dist/js/feedback/ScreenshotButton.d.ts +25 -0
- package/ts3.8/dist/js/feedback/defaults.d.ts +3 -1
- package/ts3.8/dist/js/feedback/icons.d.ts +30 -0
- package/ts3.8/dist/js/feedback/integration.d.ts +19 -2
- package/ts3.8/dist/js/feedback/lazy.d.ts +10 -0
- package/ts3.8/dist/js/index.d.ts +5 -3
- package/ts3.8/dist/js/integrations/breadcrumbs.d.ts +47 -0
- package/ts3.8/dist/js/integrations/exports.d.ts +2 -1
- package/ts3.8/dist/js/options.d.ts +4 -2
- package/ts3.8/dist/js/playground/animations.d.ts +4 -0
- package/ts3.8/dist/js/playground/examples.d.ts +13 -0
- package/ts3.8/dist/js/playground/images.d.ts +4 -0
- package/ts3.8/dist/js/playground/index.d.ts +2 -0
- package/ts3.8/dist/js/playground/modal.d.ts +29 -0
- package/ts3.8/dist/js/replay/browserReplay.d.ts +13 -1
- package/ts3.8/dist/js/replay/mobilereplay.d.ts +14 -1
- package/ts3.8/dist/js/replay/replayInterface.d.ts +52 -0
- package/ts3.8/dist/js/sdk.d.ts +1 -6
- package/ts3.8/dist/js/tracing/integrations/appStart.d.ts +7 -1
- package/ts3.8/dist/js/transports/encodePolyfill.d.ts +4 -0
- package/ts3.8/dist/js/utils/carrier.d.ts +5 -0
- package/ts3.8/dist/js/utils/encode.d.ts +5 -0
- package/ts3.8/dist/js/utils/expoglobalobject.d.ts +2 -1
- package/ts3.8/dist/js/utils/expomodules.d.ts +5 -1
- package/ts3.8/dist/js/utils/worldwide.d.ts +10 -2
- package/ts3.8/dist/js/version.d.ts +1 -1
- package/ts3.8/dist/js/wrapper.d.ts +1 -0
|
@@ -7,15 +7,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { captureFeedback, getCurrentScope, lastEventId, logger } from '@sentry/core';
|
|
10
|
+
import { captureFeedback, getCurrentScope, getGlobalScope, getIsolationScope, lastEventId, logger } from '@sentry/core';
|
|
11
11
|
import * as React from 'react';
|
|
12
|
-
import { Image, Keyboard, Text, TextInput, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native';
|
|
13
|
-
import { isWeb, notWeb } from '../utils/environment';
|
|
14
|
-
import { getDataFromUri } from '../wrapper';
|
|
12
|
+
import { Appearance, Image, Keyboard, Text, TextInput, TouchableOpacity, TouchableWithoutFeedback, View } from 'react-native';
|
|
13
|
+
import { isExpoGo, isWeb, notWeb } from '../utils/environment';
|
|
14
|
+
import { getDataFromUri, NATIVE } from '../wrapper';
|
|
15
15
|
import { sentryLogo } from './branding';
|
|
16
16
|
import { defaultConfiguration } from './defaults';
|
|
17
17
|
import defaultStyles from './FeedbackWidget.styles';
|
|
18
|
+
import { getTheme } from './FeedbackWidget.theme';
|
|
19
|
+
import { hideFeedbackButton, showScreenshotButton } from './FeedbackWidgetManager';
|
|
18
20
|
import { lazyLoadFeedbackIntegration } from './lazy';
|
|
21
|
+
import { getCapturedScreenshot } from './ScreenshotButton';
|
|
19
22
|
import { base64ToUint8Array, feedbackAlertDialog, isValidEmail } from './utils';
|
|
20
23
|
/**
|
|
21
24
|
* @beta
|
|
@@ -23,7 +26,7 @@ import { base64ToUint8Array, feedbackAlertDialog, isValidEmail } from './utils';
|
|
|
23
26
|
*/
|
|
24
27
|
export class FeedbackWidget extends React.Component {
|
|
25
28
|
constructor(props) {
|
|
26
|
-
var _a, _b, _c, _d, _e, _f
|
|
29
|
+
var _a, _b, _c, _d, _e, _f;
|
|
27
30
|
super(props);
|
|
28
31
|
this._didSubmitForm = false;
|
|
29
32
|
this.handleFeedbackSubmit = () => {
|
|
@@ -33,11 +36,15 @@ export class FeedbackWidget extends React.Component {
|
|
|
33
36
|
const trimmedName = name === null || name === void 0 ? void 0 : name.trim();
|
|
34
37
|
const trimmedEmail = email === null || email === void 0 ? void 0 : email.trim();
|
|
35
38
|
const trimmedDescription = description === null || description === void 0 ? void 0 : description.trim();
|
|
36
|
-
if ((this.props.isNameRequired && !trimmedName) ||
|
|
39
|
+
if ((this.props.isNameRequired && !trimmedName) ||
|
|
40
|
+
(this.props.isEmailRequired && !trimmedEmail) ||
|
|
41
|
+
!trimmedDescription) {
|
|
37
42
|
feedbackAlertDialog(text.errorTitle, text.formError);
|
|
38
43
|
return;
|
|
39
44
|
}
|
|
40
|
-
if (this.props.shouldValidateEmail &&
|
|
45
|
+
if (this.props.shouldValidateEmail &&
|
|
46
|
+
(this.props.isEmailRequired || trimmedEmail.length > 0) &&
|
|
47
|
+
!isValidEmail(trimmedEmail)) {
|
|
41
48
|
feedbackAlertDialog(text.errorTitle, text.emailError);
|
|
42
49
|
return;
|
|
43
50
|
}
|
|
@@ -61,7 +68,12 @@ export class FeedbackWidget extends React.Component {
|
|
|
61
68
|
this.setState({ isVisible: false });
|
|
62
69
|
}
|
|
63
70
|
captureFeedback(userFeedback, attachments ? { attachments } : undefined);
|
|
64
|
-
onSubmitSuccess({
|
|
71
|
+
onSubmitSuccess({
|
|
72
|
+
name: trimmedName,
|
|
73
|
+
email: trimmedEmail,
|
|
74
|
+
message: trimmedDescription,
|
|
75
|
+
attachments: attachments,
|
|
76
|
+
});
|
|
65
77
|
feedbackAlertDialog(text.successMessageText, '');
|
|
66
78
|
onFormSubmitted();
|
|
67
79
|
this._didSubmitForm = true;
|
|
@@ -74,17 +86,17 @@ export class FeedbackWidget extends React.Component {
|
|
|
74
86
|
}
|
|
75
87
|
};
|
|
76
88
|
this.onScreenshotButtonPress = () => __awaiter(this, void 0, void 0, function* () {
|
|
77
|
-
var
|
|
78
|
-
if (!this.
|
|
89
|
+
var _g, _h, _j, _k, _l;
|
|
90
|
+
if (!this._hasScreenshot()) {
|
|
79
91
|
const { imagePicker } = this.props;
|
|
80
92
|
if (imagePicker) {
|
|
81
93
|
const launchImageLibrary = imagePicker.launchImageLibraryAsync
|
|
82
|
-
// expo-image-picker library is available
|
|
83
|
-
|
|
84
|
-
// react-native-image-picker library is available
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
? // expo-image-picker library is available
|
|
95
|
+
() => { var _a; return (_a = imagePicker.launchImageLibraryAsync) === null || _a === void 0 ? void 0 : _a.call(imagePicker, { mediaTypes: ['images'], base64: isWeb() }); }
|
|
96
|
+
: // react-native-image-picker library is available
|
|
97
|
+
imagePicker.launchImageLibrary
|
|
98
|
+
? () => { var _a; return (_a = imagePicker.launchImageLibrary) === null || _a === void 0 ? void 0 : _a.call(imagePicker, { mediaType: 'photo', includeBase64: isWeb() }); }
|
|
99
|
+
: null;
|
|
88
100
|
if (!launchImageLibrary) {
|
|
89
101
|
logger.warn('No compatible image picker library found. Please provide a valid image picker library.');
|
|
90
102
|
if (__DEV__) {
|
|
@@ -95,9 +107,9 @@ export class FeedbackWidget extends React.Component {
|
|
|
95
107
|
const result = yield launchImageLibrary();
|
|
96
108
|
if ((result === null || result === void 0 ? void 0 : result.assets) && result.assets.length > 0) {
|
|
97
109
|
if (isWeb()) {
|
|
98
|
-
const filename = (
|
|
99
|
-
const imageUri = (
|
|
100
|
-
const base64 = (
|
|
110
|
+
const filename = (_g = result.assets[0]) === null || _g === void 0 ? void 0 : _g.fileName;
|
|
111
|
+
const imageUri = (_h = result.assets[0]) === null || _h === void 0 ? void 0 : _h.uri;
|
|
112
|
+
const base64 = (_j = result.assets[0]) === null || _j === void 0 ? void 0 : _j.base64;
|
|
101
113
|
const data = base64 ? base64ToUint8Array(base64) : undefined;
|
|
102
114
|
if (data) {
|
|
103
115
|
this.setState({ filename, attachment: data, attachmentUri: imageUri });
|
|
@@ -107,18 +119,23 @@ export class FeedbackWidget extends React.Component {
|
|
|
107
119
|
}
|
|
108
120
|
}
|
|
109
121
|
else {
|
|
110
|
-
const filename = (
|
|
111
|
-
const imageUri = (
|
|
112
|
-
imageUri &&
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
const filename = (_k = result.assets[0]) === null || _k === void 0 ? void 0 : _k.fileName;
|
|
123
|
+
const imageUri = (_l = result.assets[0]) === null || _l === void 0 ? void 0 : _l.uri;
|
|
124
|
+
imageUri &&
|
|
125
|
+
getDataFromUri(imageUri)
|
|
126
|
+
.then((data) => {
|
|
127
|
+
if (data != null) {
|
|
128
|
+
this.setState({ filename, attachment: data, attachmentUri: imageUri });
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
this._showImageRetrievalDevelopmentNote();
|
|
132
|
+
logger.error('Failed to read image data from uri:', imageUri);
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
.catch((error) => {
|
|
136
|
+
this._showImageRetrievalDevelopmentNote();
|
|
137
|
+
logger.error('Failed to read image data from uri:', imageUri, 'error: ', error);
|
|
138
|
+
});
|
|
122
139
|
}
|
|
123
140
|
}
|
|
124
141
|
}
|
|
@@ -131,10 +148,11 @@ export class FeedbackWidget extends React.Component {
|
|
|
131
148
|
this.setState({ filename: 'feedback_screenshot', attachment: data, attachmentUri: uri });
|
|
132
149
|
}
|
|
133
150
|
else {
|
|
151
|
+
this._showImageRetrievalDevelopmentNote();
|
|
134
152
|
logger.error('Failed to read image data from uri:', uri);
|
|
135
153
|
}
|
|
136
|
-
})
|
|
137
|
-
.
|
|
154
|
+
}).catch((error) => {
|
|
155
|
+
this._showImageRetrievalDevelopmentNote();
|
|
138
156
|
logger.error('Failed to read image data from uri:', uri, 'error: ', error);
|
|
139
157
|
});
|
|
140
158
|
});
|
|
@@ -144,6 +162,27 @@ export class FeedbackWidget extends React.Component {
|
|
|
144
162
|
this.setState({ filename: undefined, attachment: undefined, attachmentUri: undefined });
|
|
145
163
|
}
|
|
146
164
|
});
|
|
165
|
+
this._setCapturedScreenshot = (screenshot) => {
|
|
166
|
+
if (screenshot.data != null) {
|
|
167
|
+
logger.debug('Setting captured screenshot:', screenshot.filename);
|
|
168
|
+
NATIVE.encodeToBase64(screenshot.data)
|
|
169
|
+
.then(base64String => {
|
|
170
|
+
if (base64String != null) {
|
|
171
|
+
const dataUri = `data:${screenshot.contentType};base64,${base64String}`;
|
|
172
|
+
this.setState({ filename: screenshot.filename, attachment: screenshot.data, attachmentUri: dataUri });
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
logger.error('Failed to read image data from:', screenshot.filename);
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
.catch(error => {
|
|
179
|
+
logger.error('Failed to read image data from:', screenshot.filename, 'error: ', error);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
logger.error('Failed to read image data from:', screenshot.filename);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
147
186
|
this._saveFormState = () => {
|
|
148
187
|
FeedbackWidget._savedState = Object.assign({}, this.state);
|
|
149
188
|
};
|
|
@@ -157,10 +196,29 @@ export class FeedbackWidget extends React.Component {
|
|
|
157
196
|
attachmentUri: undefined,
|
|
158
197
|
};
|
|
159
198
|
};
|
|
199
|
+
this._hasScreenshot = () => {
|
|
200
|
+
return this.state.filename !== undefined && this.state.attachment !== undefined && this.state.attachmentUri !== undefined;
|
|
201
|
+
};
|
|
202
|
+
this._getUser = () => {
|
|
203
|
+
const currentUser = getCurrentScope().getUser();
|
|
204
|
+
if (currentUser) {
|
|
205
|
+
return currentUser;
|
|
206
|
+
}
|
|
207
|
+
const isolationUser = getIsolationScope().getUser();
|
|
208
|
+
if (isolationUser) {
|
|
209
|
+
return isolationUser;
|
|
210
|
+
}
|
|
211
|
+
return getGlobalScope().getUser();
|
|
212
|
+
};
|
|
213
|
+
this._showImageRetrievalDevelopmentNote = () => {
|
|
214
|
+
if (isExpoGo()) {
|
|
215
|
+
feedbackAlertDialog('Development note', 'The feedback widget cannot retrieve image data in Expo Go. Please build your app to test this functionality.');
|
|
216
|
+
}
|
|
217
|
+
};
|
|
160
218
|
const currentUser = {
|
|
161
219
|
useSentryUser: {
|
|
162
|
-
email: ((_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.useSentryUser) === null || _b === void 0 ? void 0 : _b.email) || ((
|
|
163
|
-
name: ((
|
|
220
|
+
email: ((_b = (_a = this.props) === null || _a === void 0 ? void 0 : _a.useSentryUser) === null || _b === void 0 ? void 0 : _b.email) || ((_c = this._getUser()) === null || _c === void 0 ? void 0 : _c.email) || '',
|
|
221
|
+
name: ((_e = (_d = this.props) === null || _d === void 0 ? void 0 : _d.useSentryUser) === null || _e === void 0 ? void 0 : _e.name) || ((_f = this._getUser()) === null || _f === void 0 ? void 0 : _f.name) || '',
|
|
164
222
|
}
|
|
165
223
|
};
|
|
166
224
|
this.state = {
|
|
@@ -175,7 +233,28 @@ export class FeedbackWidget extends React.Component {
|
|
|
175
233
|
lazyLoadFeedbackIntegration();
|
|
176
234
|
}
|
|
177
235
|
/**
|
|
178
|
-
*
|
|
236
|
+
* For testing purposes only.
|
|
237
|
+
*/
|
|
238
|
+
static reset() {
|
|
239
|
+
FeedbackWidget._savedState = {
|
|
240
|
+
name: '',
|
|
241
|
+
email: '',
|
|
242
|
+
description: '',
|
|
243
|
+
filename: undefined,
|
|
244
|
+
attachment: undefined,
|
|
245
|
+
attachmentUri: undefined,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Add a listener to the theme change event.
|
|
250
|
+
*/
|
|
251
|
+
componentDidMount() {
|
|
252
|
+
this._themeListener = Appearance.addChangeListener(() => {
|
|
253
|
+
this.forceUpdate();
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Save the state before unmounting the component and remove the theme listener.
|
|
179
258
|
*/
|
|
180
259
|
componentWillUnmount() {
|
|
181
260
|
if (this._didSubmitForm) {
|
|
@@ -185,17 +264,21 @@ export class FeedbackWidget extends React.Component {
|
|
|
185
264
|
else {
|
|
186
265
|
this._saveFormState();
|
|
187
266
|
}
|
|
267
|
+
if (this._themeListener) {
|
|
268
|
+
this._themeListener.remove();
|
|
269
|
+
}
|
|
188
270
|
}
|
|
189
271
|
/**
|
|
190
272
|
* Renders the feedback form screen.
|
|
191
273
|
*/
|
|
192
274
|
render() {
|
|
275
|
+
const theme = getTheme();
|
|
193
276
|
const { name, email, description } = this.state;
|
|
194
277
|
const { onFormClose } = this.props;
|
|
195
278
|
const config = this.props;
|
|
196
279
|
const imagePickerConfiguration = this.props;
|
|
197
280
|
const text = this.props;
|
|
198
|
-
const styles = Object.assign(Object.assign({}, defaultStyles), this.props.styles);
|
|
281
|
+
const styles = Object.assign(Object.assign({}, defaultStyles(theme)), this.props.styles);
|
|
199
282
|
const onCancel = () => {
|
|
200
283
|
if (onFormClose) {
|
|
201
284
|
onFormClose();
|
|
@@ -207,33 +290,46 @@ export class FeedbackWidget extends React.Component {
|
|
|
207
290
|
if (!this.state.isVisible) {
|
|
208
291
|
return null;
|
|
209
292
|
}
|
|
210
|
-
|
|
293
|
+
const screenshot = getCapturedScreenshot();
|
|
294
|
+
if (screenshot === 'ErrorCapturingScreenshot') {
|
|
295
|
+
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
296
|
+
feedbackAlertDialog(text.errorTitle, text.captureScreenshotError);
|
|
297
|
+
}), 100);
|
|
298
|
+
}
|
|
299
|
+
else if (screenshot) {
|
|
300
|
+
this._setCapturedScreenshot(screenshot);
|
|
301
|
+
}
|
|
302
|
+
return (React.createElement(TouchableWithoutFeedback, { onPress: notWeb() ? Keyboard.dismiss : undefined, accessible: false, accessibilityElementsHidden: false },
|
|
211
303
|
React.createElement(View, { style: styles.container },
|
|
212
304
|
React.createElement(View, { style: styles.titleContainer },
|
|
213
|
-
React.createElement(Text, { style: styles.title }, text.formTitle),
|
|
214
|
-
config.showBranding && (React.createElement(Image, { source: { uri: sentryLogo }, style: styles.sentryLogo, testID:
|
|
305
|
+
React.createElement(Text, { style: styles.title, testID: "sentry-feedback-form-title" }, text.formTitle),
|
|
306
|
+
config.showBranding && (React.createElement(Image, { source: { uri: sentryLogo }, style: styles.sentryLogo, testID: "sentry-logo" }))),
|
|
215
307
|
config.showName && (React.createElement(React.Fragment, null,
|
|
216
308
|
React.createElement(Text, { style: styles.label },
|
|
217
309
|
text.nameLabel,
|
|
218
310
|
config.isNameRequired && ` ${text.isRequiredLabel}`),
|
|
219
|
-
React.createElement(TextInput, { style: styles.input, placeholder: text.namePlaceholder, value: name, onChangeText:
|
|
311
|
+
React.createElement(TextInput, { style: styles.input, testID: "sentry-feedback-name-input", placeholder: text.namePlaceholder, value: name, onChangeText: value => this.setState({ name: value }) }))),
|
|
220
312
|
config.showEmail && (React.createElement(React.Fragment, null,
|
|
221
313
|
React.createElement(Text, { style: styles.label },
|
|
222
314
|
text.emailLabel,
|
|
223
315
|
config.isEmailRequired && ` ${text.isRequiredLabel}`),
|
|
224
|
-
React.createElement(TextInput, { style: styles.input, placeholder: text.emailPlaceholder, keyboardType: 'email-address', value: email, onChangeText:
|
|
316
|
+
React.createElement(TextInput, { style: styles.input, testID: "sentry-feedback-email-input", placeholder: text.emailPlaceholder, keyboardType: 'email-address', value: email, onChangeText: value => this.setState({ email: value }) }))),
|
|
225
317
|
React.createElement(Text, { style: styles.label },
|
|
226
318
|
text.messageLabel,
|
|
227
319
|
` ${text.isRequiredLabel}`),
|
|
228
|
-
React.createElement(TextInput, { style: [styles.input, styles.textArea], placeholder: text.messagePlaceholder, value: description, onChangeText:
|
|
229
|
-
(config.enableScreenshot || imagePickerConfiguration.imagePicker) && (React.createElement(View, { style: styles.screenshotContainer },
|
|
320
|
+
React.createElement(TextInput, { style: [styles.input, styles.textArea], testID: "sentry-feedback-message-input", placeholder: text.messagePlaceholder, value: description, onChangeText: value => this.setState({ description: value }), multiline: true }),
|
|
321
|
+
(config.enableScreenshot || imagePickerConfiguration.imagePicker || this._hasScreenshot()) && (React.createElement(View, { style: styles.screenshotContainer },
|
|
230
322
|
this.state.attachmentUri && (React.createElement(Image, { source: { uri: this.state.attachmentUri }, style: styles.screenshotThumbnail })),
|
|
231
323
|
React.createElement(TouchableOpacity, { style: styles.screenshotButton, onPress: this.onScreenshotButtonPress },
|
|
232
|
-
React.createElement(Text, { style: styles.screenshotText }, !this.
|
|
233
|
-
|
|
234
|
-
|
|
324
|
+
React.createElement(Text, { style: styles.screenshotText }, !this._hasScreenshot() ? text.addScreenshotButtonLabel : text.removeScreenshotButtonLabel)))),
|
|
325
|
+
notWeb() && config.enableTakeScreenshot && !this.state.attachmentUri && (React.createElement(TouchableOpacity, { style: styles.takeScreenshotButton, onPress: () => {
|
|
326
|
+
hideFeedbackButton();
|
|
327
|
+
onCancel();
|
|
328
|
+
showScreenshotButton();
|
|
329
|
+
} },
|
|
330
|
+
React.createElement(Text, { style: styles.takeScreenshotText, testID: 'sentry-feedback-take-screenshot-button' }, text.captureScreenshotButtonLabel))),
|
|
235
331
|
React.createElement(TouchableOpacity, { style: styles.submitButton, onPress: this.handleFeedbackSubmit },
|
|
236
|
-
React.createElement(Text, { style: styles.submitText }, text.submitButtonLabel)),
|
|
332
|
+
React.createElement(Text, { style: styles.submitText, testID: "sentry-feedback-submit-button" }, text.submitButtonLabel)),
|
|
237
333
|
React.createElement(TouchableOpacity, { style: styles.cancelButton, onPress: onCancel },
|
|
238
334
|
React.createElement(Text, { style: styles.cancelText }, text.cancelButtonLabel)))));
|
|
239
335
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeedbackWidget.js","sourceRoot":"","sources":["../../../src/js/feedback/FeedbackWidget.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { SendFeedbackParams } from '@sentry/core';\nimport { captureFeedback, getCurrentScope, lastEventId, logger } from '@sentry/core';\nimport * as React from 'react';\nimport type { KeyboardTypeOptions } from 'react-native';\nimport {\n Image,\n Keyboard,\n Text,\n TextInput,\n TouchableOpacity,\n TouchableWithoutFeedback,\n View\n} from 'react-native';\n\nimport { isWeb, notWeb } from '../utils/environment';\nimport { getDataFromUri } from '../wrapper';\nimport { sentryLogo } from './branding';\nimport { defaultConfiguration } from './defaults';\nimport defaultStyles from './FeedbackWidget.styles';\nimport type { FeedbackGeneralConfiguration, FeedbackTextConfiguration, FeedbackWidgetProps, FeedbackWidgetState, FeedbackWidgetStyles, ImagePickerConfiguration } from './FeedbackWidget.types';\nimport { lazyLoadFeedbackIntegration } from './lazy';\nimport { base64ToUint8Array, feedbackAlertDialog, isValidEmail } from './utils';\n\n/**\n * @beta\n * Implements a feedback form screen that sends feedback to Sentry using Sentry.captureFeedback.\n */\nexport class FeedbackWidget extends React.Component<FeedbackWidgetProps, FeedbackWidgetState> {\n public static defaultProps = defaultConfiguration;\n\n private static _savedState: Omit<FeedbackWidgetState, 'isVisible'> = {\n name: '',\n email: '',\n description: '',\n filename: undefined,\n attachment: undefined,\n attachmentUri: undefined,\n };\n\n private _didSubmitForm: boolean = false;\n\n public constructor(props: FeedbackWidgetProps) {\n super(props);\n\n const currentUser = {\n useSentryUser: {\n email: this.props?.useSentryUser?.email || getCurrentScope()?.getUser()?.email || '',\n name: this.props?.useSentryUser?.name || getCurrentScope()?.getUser()?.name || '',\n }\n }\n\n this.state = {\n isVisible: true,\n name: FeedbackWidget._savedState.name || currentUser.useSentryUser.name,\n email: FeedbackWidget._savedState.email || currentUser.useSentryUser.email,\n description: FeedbackWidget._savedState.description || '',\n filename: FeedbackWidget._savedState.filename || undefined,\n attachment: FeedbackWidget._savedState.attachment || undefined,\n attachmentUri: FeedbackWidget._savedState.attachmentUri || undefined,\n };\n\n lazyLoadFeedbackIntegration();\n }\n\n public handleFeedbackSubmit: () => void = () => {\n const { name, email, description } = this.state;\n const { onSubmitSuccess, onSubmitError, onFormSubmitted } = this.props;\n const text = this.props;\n\n const trimmedName = name?.trim();\n const trimmedEmail = email?.trim();\n const trimmedDescription = description?.trim();\n\n if ((this.props.isNameRequired && !trimmedName) || (this.props.isEmailRequired && !trimmedEmail) || !trimmedDescription) {\n feedbackAlertDialog(text.errorTitle, text.formError);\n return;\n }\n\n if (this.props.shouldValidateEmail && (this.props.isEmailRequired || trimmedEmail.length > 0) && !isValidEmail(trimmedEmail)) {\n feedbackAlertDialog(text.errorTitle, text.emailError);\n return;\n }\n\n const attachments = this.state.filename && this.state.attachment\n ? [\n {\n filename: this.state.filename,\n data: this.state.attachment,\n },\n ]\n : undefined;\n\n const eventId = lastEventId();\n const userFeedback: SendFeedbackParams = {\n message: trimmedDescription,\n name: trimmedName,\n email: trimmedEmail,\n associatedEventId: eventId,\n };\n\n try {\n if (!onFormSubmitted) {\n this.setState({ isVisible: false });\n }\n captureFeedback(userFeedback, attachments ? { attachments } : undefined);\n onSubmitSuccess({ name: trimmedName, email: trimmedEmail, message: trimmedDescription, attachments: attachments });\n feedbackAlertDialog(text.successMessageText , '');\n onFormSubmitted();\n this._didSubmitForm = true;\n } catch (error) {\n const errorString = `Feedback form submission failed: ${error}`;\n onSubmitError(new Error(errorString));\n feedbackAlertDialog(text.errorTitle, text.genericError);\n logger.error(`Feedback form submission failed: ${error}`);\n }\n };\n\n public onScreenshotButtonPress: () => void = async () => {\n if (!this.state.filename && !this.state.attachment) {\n const { imagePicker } = this.props;\n if (imagePicker) {\n const launchImageLibrary = imagePicker.launchImageLibraryAsync\n // expo-image-picker library is available\n ? () => imagePicker.launchImageLibraryAsync?.({ mediaTypes: ['images'], base64: isWeb() })\n // react-native-image-picker library is available\n : imagePicker.launchImageLibrary\n ? () => imagePicker.launchImageLibrary?.({ mediaType: 'photo', includeBase64: isWeb() })\n : null;\n if (!launchImageLibrary) {\n logger.warn('No compatible image picker library found. Please provide a valid image picker library.');\n if (__DEV__) {\n feedbackAlertDialog(\n 'Development note',\n 'No compatible image picker library found. Please provide a compatible version of `expo-image-picker` or `react-native-image-picker`.',\n );\n }\n return;\n }\n\n const result = await launchImageLibrary();\n if (result?.assets && result.assets.length > 0) {\n if (isWeb()) {\n const filename = result.assets[0]?.fileName;\n const imageUri = result.assets[0]?.uri;\n const base64 = result.assets[0]?.base64;\n const data = base64 ? base64ToUint8Array(base64) : undefined;\n if (data) {\n this.setState({ filename, attachment: data, attachmentUri: imageUri });\n } else {\n logger.error('Failed to read image data on the web');\n }\n } else {\n const filename = result.assets[0]?.fileName;\n const imageUri = result.assets[0]?.uri;\n imageUri && getDataFromUri(imageUri).then((data) => {\n if (data) {\n this.setState({ filename, attachment: data, attachmentUri: imageUri });\n } else {\n logger.error('Failed to read image data from uri:', imageUri);\n }\n }).catch((error) => {\n logger.error('Failed to read image data from uri:', imageUri, 'error: ', error);\n });\n }\n }\n } else {\n // Defaulting to the onAddScreenshot callback\n const { onAddScreenshot } = { ...defaultConfiguration, ...this.props };\n onAddScreenshot((uri: string) => {\n getDataFromUri(uri).then((data) => {\n if (data != null) {\n this.setState({ filename: 'feedback_screenshot', attachment: data, attachmentUri: uri });\n } else {\n logger.error('Failed to read image data from uri:', uri);\n }\n })\n .catch((error) => {\n logger.error('Failed to read image data from uri:', uri, 'error: ', error);\n });\n });\n }\n } else {\n this.setState({ filename: undefined, attachment: undefined, attachmentUri: undefined });\n }\n }\n\n /**\n * Save the state before unmounting the component.\n */\n public componentWillUnmount(): void {\n if (this._didSubmitForm) {\n this._clearFormState();\n this._didSubmitForm = false;\n } else {\n this._saveFormState();\n }\n }\n\n /**\n * Renders the feedback form screen.\n */\n public render(): React.ReactNode {\n const { name, email, description } = this.state;\n const { onFormClose } = this.props;\n const config: FeedbackGeneralConfiguration = this.props;\n const imagePickerConfiguration: ImagePickerConfiguration = this.props;\n const text: FeedbackTextConfiguration = this.props;\n const styles: FeedbackWidgetStyles = { ...defaultStyles, ...this.props.styles };\n const onCancel = (): void => {\n if (onFormClose) {\n onFormClose();\n } else {\n this.setState({ isVisible: false });\n }\n }\n\n if (!this.state.isVisible) {\n return null;\n }\n\n return (\n <TouchableWithoutFeedback onPress={notWeb() ? Keyboard.dismiss: undefined}>\n <View style={styles.container}>\n <View style={styles.titleContainer}>\n <Text style={styles.title}>{text.formTitle}</Text>\n {config.showBranding && (\n <Image\n source={{ uri: sentryLogo }}\n style={styles.sentryLogo}\n testID='sentry-logo'\n />\n )}\n </View>\n\n {config.showName && (\n <>\n <Text style={styles.label}>\n {text.nameLabel}\n {config.isNameRequired && ` ${text.isRequiredLabel}`}\n </Text>\n <TextInput\n style={styles.input}\n placeholder={text.namePlaceholder}\n value={name}\n onChangeText={(value) => this.setState({ name: value })}\n />\n </>\n )}\n\n {config.showEmail && (\n <>\n <Text style={styles.label}>\n {text.emailLabel}\n {config.isEmailRequired && ` ${text.isRequiredLabel}`}\n </Text>\n <TextInput\n style={styles.input}\n placeholder={text.emailPlaceholder}\n keyboardType={'email-address' as KeyboardTypeOptions}\n value={email}\n onChangeText={(value) => this.setState({ email: value })}\n />\n </>\n )}\n\n <Text style={styles.label}>\n {text.messageLabel}\n {` ${text.isRequiredLabel}`}\n </Text>\n <TextInput\n style={[styles.input, styles.textArea]}\n placeholder={text.messagePlaceholder}\n value={description}\n onChangeText={(value) => this.setState({ description: value })}\n multiline\n />\n {(config.enableScreenshot || imagePickerConfiguration.imagePicker) && (\n <View style={styles.screenshotContainer}>\n {this.state.attachmentUri && (\n <Image\n source={{ uri: this.state.attachmentUri }}\n style={styles.screenshotThumbnail}\n />\n )}\n <TouchableOpacity style={styles.screenshotButton} onPress={this.onScreenshotButtonPress}>\n <Text style={styles.screenshotText}>\n {!this.state.filename && !this.state.attachment\n ? text.addScreenshotButtonLabel\n : text.removeScreenshotButtonLabel}\n </Text>\n </TouchableOpacity>\n </View>\n )}\n <TouchableOpacity style={styles.submitButton} onPress={this.handleFeedbackSubmit}>\n <Text style={styles.submitText}>{text.submitButtonLabel}</Text>\n </TouchableOpacity>\n\n <TouchableOpacity style={styles.cancelButton} onPress={onCancel}>\n <Text style={styles.cancelText}>{text.cancelButtonLabel}</Text>\n </TouchableOpacity>\n </View>\n </TouchableWithoutFeedback>\n );\n }\n\n private _saveFormState = (): void => {\n FeedbackWidget._savedState = { ...this.state };\n };\n\n private _clearFormState = (): void => {\n FeedbackWidget._savedState = {\n name: '',\n email: '',\n description: '',\n filename: undefined,\n attachment: undefined,\n attachmentUri: undefined,\n };\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"FeedbackWidget.js","sourceRoot":"","sources":["../../../src/js/feedback/FeedbackWidget.tsx"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-lines */\nimport type { SendFeedbackParams, User } from '@sentry/core';\nimport { captureFeedback, getCurrentScope, getGlobalScope, getIsolationScope, lastEventId, logger } from '@sentry/core';\nimport * as React from 'react';\nimport type { KeyboardTypeOptions ,\n NativeEventSubscription} from 'react-native';\nimport {\n Appearance,\n Image,\n Keyboard,\n Text,\n TextInput,\n TouchableOpacity,\n TouchableWithoutFeedback,\n View\n} from 'react-native';\nimport { isExpoGo, isWeb, notWeb } from '../utils/environment';\nimport type { Screenshot } from '../wrapper';\nimport { getDataFromUri, NATIVE } from '../wrapper';\nimport { sentryLogo } from './branding';\nimport { defaultConfiguration } from './defaults';\nimport defaultStyles from './FeedbackWidget.styles';\nimport { getTheme } from './FeedbackWidget.theme';\nimport type { FeedbackGeneralConfiguration, FeedbackTextConfiguration, FeedbackWidgetProps, FeedbackWidgetState, FeedbackWidgetStyles, ImagePickerConfiguration } from './FeedbackWidget.types';\nimport { hideFeedbackButton, showScreenshotButton } from './FeedbackWidgetManager';\nimport { lazyLoadFeedbackIntegration } from './lazy';\nimport { getCapturedScreenshot } from './ScreenshotButton';\nimport { base64ToUint8Array, feedbackAlertDialog, isValidEmail } from './utils';\n\n/**\n * @beta\n * Implements a feedback form screen that sends feedback to Sentry using Sentry.captureFeedback.\n */\nexport class FeedbackWidget extends React.Component<FeedbackWidgetProps, FeedbackWidgetState> {\n public static defaultProps = defaultConfiguration;\n\n private static _savedState: Omit<FeedbackWidgetState, 'isVisible'> = {\n name: '',\n email: '',\n description: '',\n filename: undefined,\n attachment: undefined,\n attachmentUri: undefined,\n };\n\n private _themeListener: NativeEventSubscription | undefined;\n\n private _didSubmitForm: boolean = false;\n\n public constructor(props: FeedbackWidgetProps) {\n super(props);\n\n const currentUser = {\n useSentryUser: {\n email: this.props?.useSentryUser?.email || this._getUser()?.email || '',\n name: this.props?.useSentryUser?.name || this._getUser()?.name || '',\n }\n }\n\n this.state = {\n isVisible: true,\n name: FeedbackWidget._savedState.name || currentUser.useSentryUser.name,\n email: FeedbackWidget._savedState.email || currentUser.useSentryUser.email,\n description: FeedbackWidget._savedState.description || '',\n filename: FeedbackWidget._savedState.filename || undefined,\n attachment: FeedbackWidget._savedState.attachment || undefined,\n attachmentUri: FeedbackWidget._savedState.attachmentUri || undefined,\n };\n\n lazyLoadFeedbackIntegration();\n }\n\n /**\n * For testing purposes only.\n */\n public static reset(): void {\n FeedbackWidget._savedState = {\n name: '',\n email: '',\n description: '',\n filename: undefined,\n attachment: undefined,\n attachmentUri: undefined,\n };\n }\n\n public handleFeedbackSubmit: () => void = () => {\n const { name, email, description } = this.state;\n const { onSubmitSuccess, onSubmitError, onFormSubmitted } = this.props;\n const text = this.props;\n\n const trimmedName = name?.trim();\n const trimmedEmail = email?.trim();\n const trimmedDescription = description?.trim();\n\n if (\n (this.props.isNameRequired && !trimmedName) ||\n (this.props.isEmailRequired && !trimmedEmail) ||\n !trimmedDescription\n ) {\n feedbackAlertDialog(text.errorTitle, text.formError);\n return;\n }\n\n if (\n this.props.shouldValidateEmail &&\n (this.props.isEmailRequired || trimmedEmail.length > 0) &&\n !isValidEmail(trimmedEmail)\n ) {\n feedbackAlertDialog(text.errorTitle, text.emailError);\n return;\n }\n\n const attachments =\n this.state.filename && this.state.attachment\n ? [\n {\n filename: this.state.filename,\n data: this.state.attachment,\n },\n ]\n : undefined;\n\n const eventId = lastEventId();\n const userFeedback: SendFeedbackParams = {\n message: trimmedDescription,\n name: trimmedName,\n email: trimmedEmail,\n associatedEventId: eventId,\n };\n\n try {\n if (!onFormSubmitted) {\n this.setState({ isVisible: false });\n }\n captureFeedback(userFeedback, attachments ? { attachments } : undefined);\n onSubmitSuccess({\n name: trimmedName,\n email: trimmedEmail,\n message: trimmedDescription,\n attachments: attachments,\n });\n feedbackAlertDialog(text.successMessageText, '');\n onFormSubmitted();\n this._didSubmitForm = true;\n } catch (error) {\n const errorString = `Feedback form submission failed: ${error}`;\n onSubmitError(new Error(errorString));\n feedbackAlertDialog(text.errorTitle, text.genericError);\n logger.error(`Feedback form submission failed: ${error}`);\n }\n };\n\n public onScreenshotButtonPress: () => void = async () => {\n if (!this._hasScreenshot()) {\n const { imagePicker } = this.props;\n if (imagePicker) {\n const launchImageLibrary = imagePicker.launchImageLibraryAsync\n ? // expo-image-picker library is available\n () => imagePicker.launchImageLibraryAsync?.({ mediaTypes: ['images'], base64: isWeb() })\n : // react-native-image-picker library is available\n imagePicker.launchImageLibrary\n ? () => imagePicker.launchImageLibrary?.({ mediaType: 'photo', includeBase64: isWeb() })\n : null;\n if (!launchImageLibrary) {\n logger.warn('No compatible image picker library found. Please provide a valid image picker library.');\n if (__DEV__) {\n feedbackAlertDialog(\n 'Development note',\n 'No compatible image picker library found. Please provide a compatible version of `expo-image-picker` or `react-native-image-picker`.',\n );\n }\n return;\n }\n\n const result = await launchImageLibrary();\n if (result?.assets && result.assets.length > 0) {\n if (isWeb()) {\n const filename = result.assets[0]?.fileName;\n const imageUri = result.assets[0]?.uri;\n const base64 = result.assets[0]?.base64;\n const data = base64 ? base64ToUint8Array(base64) : undefined;\n if (data) {\n this.setState({ filename, attachment: data, attachmentUri: imageUri });\n } else {\n logger.error('Failed to read image data on the web');\n }\n } else {\n const filename = result.assets[0]?.fileName;\n const imageUri = result.assets[0]?.uri;\n imageUri &&\n getDataFromUri(imageUri)\n .then((data) => {\n if (data != null) {\n this.setState({ filename, attachment: data, attachmentUri: imageUri });\n } else {\n this._showImageRetrievalDevelopmentNote();\n logger.error('Failed to read image data from uri:', imageUri);\n }\n })\n .catch((error) => {\n this._showImageRetrievalDevelopmentNote();\n logger.error('Failed to read image data from uri:', imageUri, 'error: ', error);\n });\n }\n }\n } else {\n // Defaulting to the onAddScreenshot callback\n const { onAddScreenshot } = { ...defaultConfiguration, ...this.props };\n onAddScreenshot((uri: string) => {\n getDataFromUri(uri).then((data) => {\n if (data != null) {\n this.setState({ filename: 'feedback_screenshot', attachment: data, attachmentUri: uri });\n } else {\n this._showImageRetrievalDevelopmentNote();\n logger.error('Failed to read image data from uri:', uri);\n }\n }).catch((error) => {\n this._showImageRetrievalDevelopmentNote();\n logger.error('Failed to read image data from uri:', uri, 'error: ', error);\n });\n });\n }\n } else {\n this.setState({ filename: undefined, attachment: undefined, attachmentUri: undefined });\n }\n };\n\n /**\n * Add a listener to the theme change event.\n */\n public componentDidMount(): void {\n this._themeListener = Appearance.addChangeListener(() => {\n this.forceUpdate();\n });\n }\n\n /**\n * Save the state before unmounting the component and remove the theme listener.\n */\n public componentWillUnmount(): void {\n if (this._didSubmitForm) {\n this._clearFormState();\n this._didSubmitForm = false;\n } else {\n this._saveFormState();\n }\n if (this._themeListener) {\n this._themeListener.remove();\n }\n }\n\n /**\n * Renders the feedback form screen.\n */\n public render(): React.ReactNode {\n const theme = getTheme();\n const { name, email, description } = this.state;\n const { onFormClose } = this.props;\n const config: FeedbackGeneralConfiguration = this.props;\n const imagePickerConfiguration: ImagePickerConfiguration = this.props;\n const text: FeedbackTextConfiguration = this.props;\n const styles: FeedbackWidgetStyles = { ...defaultStyles(theme), ...this.props.styles };\n const onCancel = (): void => {\n if (onFormClose) {\n onFormClose();\n } else {\n this.setState({ isVisible: false });\n }\n };\n\n if (!this.state.isVisible) {\n return null;\n }\n\n const screenshot = getCapturedScreenshot();\n if (screenshot === 'ErrorCapturingScreenshot') {\n setTimeout(async () => {\n feedbackAlertDialog(text.errorTitle, text.captureScreenshotError);\n }, 100);\n } else if (screenshot) {\n this._setCapturedScreenshot(screenshot);\n }\n\n return (\n <TouchableWithoutFeedback\n onPress={notWeb() ? Keyboard.dismiss : undefined}\n accessible={false}\n accessibilityElementsHidden={false}\n >\n <View style={styles.container}>\n <View style={styles.titleContainer}>\n <Text style={styles.title} testID=\"sentry-feedback-form-title\">\n {text.formTitle}\n </Text>\n {config.showBranding && (\n <Image source={{ uri: sentryLogo }} style={styles.sentryLogo} testID=\"sentry-logo\" />\n )}\n </View>\n\n {config.showName && (\n <>\n <Text style={styles.label}>\n {text.nameLabel}\n {config.isNameRequired && ` ${text.isRequiredLabel}`}\n </Text>\n <TextInput\n style={styles.input}\n testID=\"sentry-feedback-name-input\"\n placeholder={text.namePlaceholder}\n value={name}\n onChangeText={value => this.setState({ name: value })}\n />\n </>\n )}\n\n {config.showEmail && (\n <>\n <Text style={styles.label}>\n {text.emailLabel}\n {config.isEmailRequired && ` ${text.isRequiredLabel}`}\n </Text>\n <TextInput\n style={styles.input}\n testID=\"sentry-feedback-email-input\"\n placeholder={text.emailPlaceholder}\n keyboardType={'email-address' as KeyboardTypeOptions}\n value={email}\n onChangeText={value => this.setState({ email: value })}\n />\n </>\n )}\n\n <Text style={styles.label}>\n {text.messageLabel}\n {` ${text.isRequiredLabel}`}\n </Text>\n <TextInput\n style={[styles.input, styles.textArea]}\n testID=\"sentry-feedback-message-input\"\n placeholder={text.messagePlaceholder}\n value={description}\n onChangeText={value => this.setState({ description: value })}\n multiline\n />\n {(config.enableScreenshot || imagePickerConfiguration.imagePicker || this._hasScreenshot()) && (\n <View style={styles.screenshotContainer}>\n {this.state.attachmentUri && (\n <Image source={{ uri: this.state.attachmentUri }} style={styles.screenshotThumbnail} />\n )}\n <TouchableOpacity style={styles.screenshotButton} onPress={this.onScreenshotButtonPress}>\n <Text style={styles.screenshotText}>\n {!this._hasScreenshot() ? text.addScreenshotButtonLabel : text.removeScreenshotButtonLabel}\n </Text>\n </TouchableOpacity>\n </View>\n )}\n {notWeb() && config.enableTakeScreenshot && !this.state.attachmentUri && (\n <TouchableOpacity style={styles.takeScreenshotButton} onPress={() => {\n hideFeedbackButton();\n onCancel();\n showScreenshotButton();\n }}>\n <Text style={styles.takeScreenshotText} testID='sentry-feedback-take-screenshot-button'>{text.captureScreenshotButtonLabel}</Text>\n </TouchableOpacity>\n )}\n <TouchableOpacity style={styles.submitButton} onPress={this.handleFeedbackSubmit}>\n <Text style={styles.submitText} testID=\"sentry-feedback-submit-button\">\n {text.submitButtonLabel}\n </Text>\n </TouchableOpacity>\n\n <TouchableOpacity style={styles.cancelButton} onPress={onCancel}>\n <Text style={styles.cancelText}>{text.cancelButtonLabel}</Text>\n </TouchableOpacity>\n </View>\n </TouchableWithoutFeedback>\n );\n }\n\n private _setCapturedScreenshot = (screenshot: Screenshot): void => {\n if (screenshot.data != null) {\n logger.debug('Setting captured screenshot:', screenshot.filename);\n NATIVE.encodeToBase64(screenshot.data)\n .then(base64String => {\n if (base64String != null) {\n const dataUri = `data:${screenshot.contentType};base64,${base64String}`;\n this.setState({ filename: screenshot.filename, attachment: screenshot.data, attachmentUri: dataUri });\n } else {\n logger.error('Failed to read image data from:', screenshot.filename);\n }\n })\n .catch(error => {\n logger.error('Failed to read image data from:', screenshot.filename, 'error: ', error);\n });\n } else {\n logger.error('Failed to read image data from:', screenshot.filename);\n }\n };\n\n private _saveFormState = (): void => {\n FeedbackWidget._savedState = { ...this.state };\n };\n\n private _clearFormState = (): void => {\n FeedbackWidget._savedState = {\n name: '',\n email: '',\n description: '',\n filename: undefined,\n attachment: undefined,\n attachmentUri: undefined,\n };\n };\n\n private _hasScreenshot = (): boolean => {\n return this.state.filename !== undefined && this.state.attachment !== undefined && this.state.attachmentUri !== undefined;\n }\n\n private _getUser = (): User | undefined => {\n const currentUser = getCurrentScope().getUser();\n if (currentUser) {\n return currentUser;\n }\n const isolationUser = getIsolationScope().getUser();\n if (isolationUser) {\n return isolationUser;\n }\n return getGlobalScope().getUser();\n }\n\n private _showImageRetrievalDevelopmentNote = (): void => {\n if (isExpoGo()) {\n feedbackAlertDialog(\n 'Development note',\n 'The feedback widget cannot retrieve image data in Expo Go. Please build your app to test this functionality.',\n );\n }\n }\n}\n"]}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ViewStyle } from 'react-native';
|
|
2
|
-
import type {
|
|
3
|
-
|
|
2
|
+
import type { FeedbackWidgetTheme } from './FeedbackWidget.theme';
|
|
3
|
+
import type { FeedbackButtonStyles, FeedbackWidgetStyles } from './FeedbackWidget.types';
|
|
4
|
+
declare const defaultStyles: (theme: FeedbackWidgetTheme) => FeedbackWidgetStyles;
|
|
5
|
+
export declare const defaultButtonStyles: (theme: FeedbackWidgetTheme) => FeedbackButtonStyles;
|
|
6
|
+
export declare const defaultScreenshotButtonStyles: (theme: FeedbackWidgetTheme) => FeedbackButtonStyles;
|
|
4
7
|
export declare const modalWrapper: ViewStyle;
|
|
5
|
-
export declare const modalSheetContainer: ViewStyle;
|
|
8
|
+
export declare const modalSheetContainer: (theme: FeedbackWidgetTheme) => ViewStyle;
|
|
6
9
|
export declare const topSpacer: ViewStyle;
|
|
7
10
|
export default defaultStyles;
|
|
8
11
|
//# sourceMappingURL=FeedbackWidget.styles.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FeedbackWidget.styles.d.ts","sourceRoot":"","sources":["../../../src/js/feedback/FeedbackWidget.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"FeedbackWidget.styles.d.ts","sourceRoot":"","sources":["../../../src/js/feedback/FeedbackWidget.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAEzF,QAAA,MAAM,aAAa,UAAW,mBAAmB,KAAG,oBA2GnD,CAAC;AAEF,eAAO,MAAM,mBAAmB,UAAW,mBAAmB,KAAG,oBAgChE,CAAC;AAEF,eAAO,MAAM,6BAA6B,UAlCC,mBAAmB,KAAG,oBAkCD,CAAC;AAEjE,eAAO,MAAM,YAAY,EAAE,SAM1B,CAAC;AAEF,eAAO,MAAM,mBAAmB,UAAW,mBAAmB,KAAG,SAchE,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,SAEvB,CAAC;AAEF,eAAe,aAAa,CAAC"}
|