From 9282172835995f44214933c444deb06263f94050 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:47:37 +0100 Subject: [PATCH 01/28] fix(expo): Upload script should not log out env file not found errors (#4332) --- CHANGELOG.md | 1 + packages/core/scripts/expo-upload-sourcemaps.js | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40c709851d..74ab39f333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ ### Fixes - Return `lastEventId` export from `@sentry/core` ([#4315](https://github.com/getsentry/sentry-react-native/pull/4315)) +- Don't log file not found errors when loading envs in `sentry-expo-upload-sourcemaps` ([#4332](https://github.com/getsentry/sentry-react-native/pull/4332)) - Navigation Span should have no parent by default ([#4326](https://github.com/getsentry/sentry-react-native/pull/4326)) ### Dependencies diff --git a/packages/core/scripts/expo-upload-sourcemaps.js b/packages/core/scripts/expo-upload-sourcemaps.js index 997f2c84d3..c282adeb3f 100755 --- a/packages/core/scripts/expo-upload-sourcemaps.js +++ b/packages/core/scripts/expo-upload-sourcemaps.js @@ -111,8 +111,12 @@ function loadDotenv(dotenvPath) { Object.assign(process.env, dotenvResult); } catch (error) { - console.warn('⚠️ Failed to load environment variables using dotenv.'); - console.warn(error); + if (error.code === 'ENOENT') { + // noop if file does not exist + } else { + console.warn('⚠️ Failed to load environment variables using dotenv.'); + console.warn(error); + } } } From ddade0036d6c24513d7942c841b59849f5bc345c Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Fri, 6 Dec 2024 13:53:21 +0100 Subject: [PATCH 02/28] Renames FeedbackFormScreen to FeedbackForm --- CHANGELOG.md | 4 ++-- ...creen.styles.ts => FeedbackForm.styles.ts} | 0 ...eedbackFormScreen.tsx => FeedbackForm.tsx} | 8 ++++---- ...mScreen.types.ts => FeedbackForm.types.ts} | 8 ++++---- packages/core/src/js/index.ts | 2 +- ...mScreen.test.tsx => FeedbackForm.test.tsx} | 20 +++++++++---------- samples/react-native/src/App.tsx | 4 ++-- 7 files changed, 23 insertions(+), 23 deletions(-) rename packages/core/src/js/feedback/{FeedbackFormScreen.styles.ts => FeedbackForm.styles.ts} (100%) rename packages/core/src/js/feedback/{FeedbackFormScreen.tsx => FeedbackForm.tsx} (91%) rename packages/core/src/js/feedback/{FeedbackFormScreen.types.ts => FeedbackForm.types.ts} (79%) rename packages/core/test/feedback/{FeedbackFormScreen.test.tsx => FeedbackForm.test.tsx} (87%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91d3f0f9ce..40dbcec5da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,9 +39,9 @@ You can add the form component in your UI and customise it like: ```jsx - import { FeedbackFormScreen } from "@sentry/react-native"; + import { FeedbackForm } from "@sentry/react-native"; ... - { - public constructor(props: FeedbackFormScreenProps) { +export class FeedbackForm extends React.Component { + public constructor(props: FeedbackFormProps) { super(props); this.state = { name: '', diff --git a/packages/core/src/js/feedback/FeedbackFormScreen.types.ts b/packages/core/src/js/feedback/FeedbackForm.types.ts similarity index 79% rename from packages/core/src/js/feedback/FeedbackFormScreen.types.ts rename to packages/core/src/js/feedback/FeedbackForm.types.ts index dbe5ce850b..7ece6590ac 100644 --- a/packages/core/src/js/feedback/FeedbackFormScreen.types.ts +++ b/packages/core/src/js/feedback/FeedbackForm.types.ts @@ -1,9 +1,9 @@ import type { TextStyle, ViewStyle } from 'react-native'; -export interface FeedbackFormScreenProps { +export interface FeedbackFormProps { closeScreen: () => void; text: FeedbackFormText; - styles?: FeedbackFormScreenStyles; + styles?: FeedbackFormStyles; } export interface FeedbackFormText { @@ -18,7 +18,7 @@ export interface FeedbackFormText { emailError?: string; } -export interface FeedbackFormScreenStyles { +export interface FeedbackFormStyles { container?: ViewStyle; title?: TextStyle; input?: TextStyle; @@ -29,7 +29,7 @@ export interface FeedbackFormScreenStyles { cancelText?: TextStyle; } -export interface FeedbackFormScreenState { +export interface FeedbackFormState { name: string; email: string; description: string; diff --git a/packages/core/src/js/index.ts b/packages/core/src/js/index.ts index ba28710da8..5dc78efa45 100644 --- a/packages/core/src/js/index.ts +++ b/packages/core/src/js/index.ts @@ -84,4 +84,4 @@ export type { TimeToDisplayProps } from './tracing'; export { Mask, Unmask } from './replay/CustomMask'; -export { FeedbackFormScreen } from './feedback/FeedbackFormScreen'; +export { FeedbackForm } from './feedback/FeedbackForm'; diff --git a/packages/core/test/feedback/FeedbackFormScreen.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx similarity index 87% rename from packages/core/test/feedback/FeedbackFormScreen.test.tsx rename to packages/core/test/feedback/FeedbackForm.test.tsx index 3232186f7b..4f26fab428 100644 --- a/packages/core/test/feedback/FeedbackFormScreen.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -3,8 +3,8 @@ import { fireEvent, render, waitFor } from '@testing-library/react-native'; import * as React from 'react'; import { Alert } from 'react-native'; -import { FeedbackFormScreen } from '../../src/js/feedback/FeedbackFormScreen'; -import type { FeedbackFormScreenProps } from '../../src/js/feedback/FeedbackFormScreen.types'; +import { FeedbackForm } from '../../src/js/feedback/FeedbackForm'; +import type { FeedbackFormProps } from '../../src/js/feedback/FeedbackForm.types'; const mockCloseScreen = jest.fn(); @@ -14,7 +14,7 @@ jest.mock('@sentry/core', () => ({ captureFeedback: jest.fn(), })); -const defaultProps: FeedbackFormScreenProps = { +const defaultProps: FeedbackFormProps = { closeScreen: mockCloseScreen, text: { formTitle: 'Feedback Form', @@ -29,13 +29,13 @@ const defaultProps: FeedbackFormScreenProps = { }, }; -describe('FeedbackFormScreen', () => { +describe('FeedbackForm', () => { afterEach(() => { jest.clearAllMocks(); }); it('renders correctly', () => { - const { getByPlaceholderText, getByText } = render(); + const { getByPlaceholderText, getByText } = render(); expect(getByText(defaultProps.text.formTitle)).toBeTruthy(); expect(getByPlaceholderText(defaultProps.text.namePlaceholder)).toBeTruthy(); @@ -46,7 +46,7 @@ describe('FeedbackFormScreen', () => { }); it('shows an error message if required fields are empty', async () => { - const { getByText } = render(); + const { getByText } = render(); fireEvent.press(getByText(defaultProps.text.submitButton)); @@ -56,7 +56,7 @@ describe('FeedbackFormScreen', () => { }); it('shows an error message if the email is not valid', async () => { - const { getByPlaceholderText, getByText } = render(); + const { getByPlaceholderText, getByText } = render(); fireEvent.changeText(getByPlaceholderText(defaultProps.text.namePlaceholder), 'John Doe'); fireEvent.changeText(getByPlaceholderText(defaultProps.text.emailPlaceholder), 'not-an-email'); @@ -70,7 +70,7 @@ describe('FeedbackFormScreen', () => { }); it('calls captureFeedback when the form is submitted successfully', async () => { - const { getByPlaceholderText, getByText } = render(); + const { getByPlaceholderText, getByText } = render(); fireEvent.changeText(getByPlaceholderText(defaultProps.text.namePlaceholder), 'John Doe'); fireEvent.changeText(getByPlaceholderText(defaultProps.text.emailPlaceholder), 'john.doe@example.com'); @@ -88,7 +88,7 @@ describe('FeedbackFormScreen', () => { }); it('calls closeScreen when the form is submitted successfully', async () => { - const { getByPlaceholderText, getByText } = render(); + const { getByPlaceholderText, getByText } = render(); fireEvent.changeText(getByPlaceholderText(defaultProps.text.namePlaceholder), 'John Doe'); fireEvent.changeText(getByPlaceholderText(defaultProps.text.emailPlaceholder), 'john.doe@example.com'); @@ -102,7 +102,7 @@ describe('FeedbackFormScreen', () => { }); it('calls closeScreen when the cancel button is pressed', () => { - const { getByText } = render(); + const { getByText } = render(); fireEvent.press(getByText(defaultProps.text.cancelButton)); diff --git a/samples/react-native/src/App.tsx b/samples/react-native/src/App.tsx index 4599d5725c..cd2656edcf 100644 --- a/samples/react-native/src/App.tsx +++ b/samples/react-native/src/App.tsx @@ -16,7 +16,7 @@ import Animated, { // Import the Sentry React Native SDK import * as Sentry from '@sentry/react-native'; -import { FeedbackFormScreen } from '@sentry/react-native'; +import { FeedbackForm } from '@sentry/react-native'; import { SENTRY_INTERNAL_DSN } from './dsn'; import ErrorsScreen from './Screens/ErrorsScreen'; @@ -157,7 +157,7 @@ const ErrorsTabNavigator = Sentry.withProfiler( options={{ presentation: 'modal', headerShown: false }} > {(props) => ( - Date: Fri, 6 Dec 2024 14:01:34 +0100 Subject: [PATCH 03/28] Add beta label --- packages/core/src/js/feedback/FeedbackForm.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index a4e8972be5..b36029cc4e 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -8,6 +8,7 @@ import defaultStyles from './FeedbackForm.styles'; import type { FeedbackFormProps, FeedbackFormState } from './FeedbackForm.types'; /** + * @beta * Implements a feedback form screen that sends feedback to Sentry using Sentry.captureFeedback. */ export class FeedbackForm extends React.Component { From 793475679677fde090d48686116c7346dde51663 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Fri, 6 Dec 2024 14:20:51 +0100 Subject: [PATCH 04/28] Extract default text to constants --- .../core/src/js/feedback/FeedbackForm.tsx | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index b36029cc4e..9270227404 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -7,6 +7,16 @@ import { Alert, Text, TextInput, TouchableOpacity, View } from 'react-native'; import defaultStyles from './FeedbackForm.styles'; import type { FeedbackFormProps, FeedbackFormState } from './FeedbackForm.types'; +const defaultFormTitle = 'Feedback Form'; +const defaultNamePlaceholder ='Name'; +const defaultEmailPlaceholder = 'Email'; +const defaultDescriptionPlaceholder = 'Description (required)'; +const defaultSubmitButton = 'Send Feedback'; +const defaultCancelButton = 'Cancel'; +const defaultErrorTitle = 'Error'; +const defaultFormError = 'Please fill out all required fields.'; +const defaultEmailError = 'Please enter a valid email address.'; + /** * @beta * Implements a feedback form screen that sends feedback to Sentry using Sentry.captureFeedback. @@ -30,14 +40,14 @@ export class FeedbackForm extends React.Component - {text?.formTitle || 'Feedback Form'} + {text?.formTitle || defaultFormTitle} this.setState({ name: value })} /> this.setState({ email: value })} @@ -79,18 +89,18 @@ export class FeedbackForm extends React.Component this.setState({ description: value })} multiline /> - {text?.submitButton || 'Send Feedback'} + {text?.submitButton || defaultSubmitButton} - {text?.cancelButton || 'Cancel'} + {text?.cancelButton || defaultCancelButton} ); From 1332acbd803ca038d3150b48e78722f9ae2fe60e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Dec 2024 11:43:21 +0200 Subject: [PATCH 05/28] chore(deps): bump github/codeql-action from 3.27.5 to 3.27.6 (#4348) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.5 to 3.27.6. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/f09c1c0a94de965c15400f5634aa42fac8fb8f88...aa578102511db1f4524ed59b8cc2bae4f6e88195) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index cd5a22b069..c628154f14 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -44,7 +44,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # pin@v3.27.5 + uses: github/codeql-action/init@aa578102511db1f4524ed59b8cc2bae4f6e88195 # pin@v3.27.6 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -55,7 +55,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # pin@v3.27.5 + uses: github/codeql-action/autobuild@aa578102511db1f4524ed59b8cc2bae4f6e88195 # pin@v3.27.6 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions @@ -66,4 +66,4 @@ jobs: # make bootstrap # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@f09c1c0a94de965c15400f5634aa42fac8fb8f88 # pin@v3.27.5 + uses: github/codeql-action/analyze@aa578102511db1f4524ed59b8cc2bae4f6e88195 # pin@v3.27.6 From a1693629c72960e611fe49500e1e1a2d79f389e3 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 10 Dec 2024 11:20:06 +0200 Subject: [PATCH 06/28] Moves constant to a separate file and aligns naming with JS --- .../core/src/js/feedback/FeedbackForm.tsx | 40 +++++++++---------- packages/core/src/js/feedback/constants.ts | 9 +++++ 2 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 packages/core/src/js/feedback/constants.ts diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 9270227404..b110844733 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -4,19 +4,19 @@ import * as React from 'react'; import type { KeyboardTypeOptions } from 'react-native'; import { Alert, Text, TextInput, TouchableOpacity, View } from 'react-native'; +import { + CANCEL_BUTTON_LABEL, + EMAIL_ERROR, + EMAIL_PLACEHOLDER, + ERROR_TITLE, + FORM_ERROR, + FORM_TITLE, + MESSAGE_PLACEHOLDER, + NAME_PLACEHOLDER, + SUBMIT_BUTTON_LABEL} from './constants'; import defaultStyles from './FeedbackForm.styles'; import type { FeedbackFormProps, FeedbackFormState } from './FeedbackForm.types'; -const defaultFormTitle = 'Feedback Form'; -const defaultNamePlaceholder ='Name'; -const defaultEmailPlaceholder = 'Email'; -const defaultDescriptionPlaceholder = 'Description (required)'; -const defaultSubmitButton = 'Send Feedback'; -const defaultCancelButton = 'Cancel'; -const defaultErrorTitle = 'Error'; -const defaultFormError = 'Please fill out all required fields.'; -const defaultEmailError = 'Please enter a valid email address.'; - /** * @beta * Implements a feedback form screen that sends feedback to Sentry using Sentry.captureFeedback. @@ -40,14 +40,14 @@ export class FeedbackForm extends React.Component - {text?.formTitle || defaultFormTitle} + {text?.formTitle || FORM_TITLE} this.setState({ name: value })} /> this.setState({ email: value })} @@ -89,18 +89,18 @@ export class FeedbackForm extends React.Component this.setState({ description: value })} multiline /> - {text?.submitButton || defaultSubmitButton} + {text?.submitButton || SUBMIT_BUTTON_LABEL} - {text?.cancelButton || defaultCancelButton} + {text?.cancelButton || CANCEL_BUTTON_LABEL} ); diff --git a/packages/core/src/js/feedback/constants.ts b/packages/core/src/js/feedback/constants.ts new file mode 100644 index 0000000000..649cc1f86c --- /dev/null +++ b/packages/core/src/js/feedback/constants.ts @@ -0,0 +1,9 @@ +export const FORM_TITLE = 'Report a Bug'; +export const NAME_PLACEHOLDER = 'Name'; +export const EMAIL_PLACEHOLDER = 'Email'; +export const MESSAGE_PLACEHOLDER = 'Description'; +export const SUBMIT_BUTTON_LABEL = 'Send Bug Report'; +export const CANCEL_BUTTON_LABEL = 'Cancel'; +export const ERROR_TITLE = 'Error'; +export const FORM_ERROR = 'Please fill out all required fields.'; +export const EMAIL_ERROR = 'Please enter a valid email address.'; From 4b5df7a9312fd8f703f47d5df9ed1aadeb560385 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 10 Dec 2024 12:21:25 +0200 Subject: [PATCH 07/28] Adds input text labels --- .../src/js/feedback/FeedbackForm.styles.ts | 4 +++ .../core/src/js/feedback/FeedbackForm.tsx | 25 +++++++++++++++++-- .../src/js/feedback/FeedbackForm.types.ts | 5 ++++ packages/core/src/js/feedback/LabelText.tsx | 21 ++++++++++++++++ packages/core/src/js/feedback/constants.ts | 10 +++++--- 5 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 packages/core/src/js/feedback/LabelText.tsx diff --git a/packages/core/src/js/feedback/FeedbackForm.styles.ts b/packages/core/src/js/feedback/FeedbackForm.styles.ts index dbc936c7f3..88dbfd52c8 100644 --- a/packages/core/src/js/feedback/FeedbackForm.styles.ts +++ b/packages/core/src/js/feedback/FeedbackForm.styles.ts @@ -12,6 +12,10 @@ const defaultStyles = StyleSheet.create({ marginBottom: 20, textAlign: 'center', }, + label: { + marginBottom: 4, + fontSize: 16, + }, input: { height: 50, borderColor: '#ccc', diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index b110844733..ba6be6712a 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -7,15 +7,20 @@ import { Alert, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { CANCEL_BUTTON_LABEL, EMAIL_ERROR, + EMAIL_LABEL, EMAIL_PLACEHOLDER, ERROR_TITLE, FORM_ERROR, FORM_TITLE, + IS_REQUIRED_LABEL, + MESSAGE_LABEL, MESSAGE_PLACEHOLDER, + NAME_LABEL, NAME_PLACEHOLDER, SUBMIT_BUTTON_LABEL} from './constants'; import defaultStyles from './FeedbackForm.styles'; import type { FeedbackFormProps, FeedbackFormState } from './FeedbackForm.types'; +import LabelText from './LabelText'; /** * @beta @@ -72,13 +77,24 @@ export class FeedbackForm extends React.Component {text?.formTitle || FORM_TITLE} + this.setState({ name: value })} /> - + this.setState({ email: value })} /> - + = ({ label, isRequired, isRequiredLabel, styles }) => { + return ( + + {label} + {isRequired && ` ${isRequiredLabel}`} + + ); +}; + +export default LabelText; diff --git a/packages/core/src/js/feedback/constants.ts b/packages/core/src/js/feedback/constants.ts index 649cc1f86c..c30d30122f 100644 --- a/packages/core/src/js/feedback/constants.ts +++ b/packages/core/src/js/feedback/constants.ts @@ -1,7 +1,11 @@ export const FORM_TITLE = 'Report a Bug'; -export const NAME_PLACEHOLDER = 'Name'; -export const EMAIL_PLACEHOLDER = 'Email'; -export const MESSAGE_PLACEHOLDER = 'Description'; +export const NAME_PLACEHOLDER = 'Your Name'; +export const NAME_LABEL = 'Name'; +export const EMAIL_PLACEHOLDER = 'your.email@example.org'; +export const EMAIL_LABEL = 'Email'; +export const MESSAGE_PLACEHOLDER = "What's the bug? What did you expect?"; +export const MESSAGE_LABEL = 'Description'; +export const IS_REQUIRED_LABEL = '(required)'; export const SUBMIT_BUTTON_LABEL = 'Send Bug Report'; export const CANCEL_BUTTON_LABEL = 'Cancel'; export const ERROR_TITLE = 'Error'; From ddc055269a330116a386e595d3952b88af6cd24a Mon Sep 17 00:00:00 2001 From: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Date: Tue, 10 Dec 2024 12:23:42 +0100 Subject: [PATCH 08/28] Publish/6.4.0 (#4344) * chore(changelog): Copy 6.4.0-beta.1 entry * release: 6.4.0 --------- Co-authored-by: getsentry-bot Co-authored-by: getsentry-bot Co-authored-by: LucasZF --- CHANGELOG.md | 23 +++++++++++++++++++ dev-packages/e2e-tests/package.json | 4 ++-- dev-packages/type-check/package.json | 2 +- lerna.json | 2 +- packages/core/package.json | 2 +- packages/core/src/js/version.ts | 2 +- performance-tests/TestAppPlain/package.json | 2 +- performance-tests/TestAppSentry/package.json | 4 ++-- samples/expo/app.json | 6 ++--- samples/expo/package.json | 4 ++-- samples/react-native-macos/package.json | 4 ++-- samples/react-native/android/app/build.gradle | 4 ++-- .../ios/sentryreactnativesample/Info.plist | 2 +- .../sentryreactnativesampleTests/Info.plist | 2 +- samples/react-native/package.json | 4 ++-- yarn.lock | 12 +++++----- 16 files changed, 51 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74ab39f333..94e8f03e90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,29 @@ - [changelog](https://github.com/getsentry/sentry-java/blob/main/CHANGELOG.md#7181) - [diff](https://github.com/getsentry/sentry-java/compare/7.18.0...7.18.1) +## 6.4.0 + +### Features + +- Add Replay Custom Masking for iOS, Android and Web ([#4224](https://github.com/getsentry/sentry-react-native/pull/4224), [#4265](https://github.com/getsentry/sentry-react-native/pull/4265), [#4272](https://github.com/getsentry/sentry-react-native/pull/4272), [#4314](https://github.com/getsentry/sentry-react-native/pull/4314)) + + ```jsx + import * as Sentry from '@sentry/react-native'; + + const Example = () => { + return ( + + + ${"All children of Sentry.Mask will be masked."} + + + ${"Only direct children of Sentry.Unmask will be unmasked."} + + + ); + }; + ``` + ## 6.4.0-beta.1 ### Features diff --git a/dev-packages/e2e-tests/package.json b/dev-packages/e2e-tests/package.json index 53e763e4b6..ab4319cea9 100644 --- a/dev-packages/e2e-tests/package.json +++ b/dev-packages/e2e-tests/package.json @@ -1,6 +1,6 @@ { "name": "sentry-react-native-e2e-tests", - "version": "6.4.0-beta.1", + "version": "6.4.0", "private": true, "description": "Sentry React Native End to End Tests Library", "main": "dist/index.js", @@ -13,7 +13,7 @@ "devDependencies": { "@babel/preset-env": "^7.25.3", "@babel/preset-typescript": "^7.18.6", - "@sentry/react-native": "6.4.0-beta.1", + "@sentry/react-native": "6.4.0", "@sentry/utils": "8.40.0", "@types/node": "^20.9.3", "@types/react": "^18.2.64", diff --git a/dev-packages/type-check/package.json b/dev-packages/type-check/package.json index 9106fa5707..d42951bd44 100644 --- a/dev-packages/type-check/package.json +++ b/dev-packages/type-check/package.json @@ -1,7 +1,7 @@ { "name": "sentry-react-native-type-check", "private": true, - "version": "6.4.0-beta.1", + "version": "6.4.0", "scripts": { "type-check": "./run-type-check.sh" } diff --git a/lerna.json b/lerna.json index 8df6ac2db7..2570bc2d60 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "$schema": "node_modules/lerna/schemas/lerna-schema.json", - "version": "6.4.0-beta.1", + "version": "6.4.0", "packages": [ "packages/*", "dev-packages/*", diff --git a/packages/core/package.json b/packages/core/package.json index 6403cc787e..dd88c414f8 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -2,7 +2,7 @@ "name": "@sentry/react-native", "homepage": "https://github.com/getsentry/sentry-react-native", "repository": "https://github.com/getsentry/sentry-react-native", - "version": "6.4.0-beta.1", + "version": "6.4.0", "description": "Official Sentry SDK for react-native", "typings": "dist/js/index.d.ts", "types": "dist/js/index.d.ts", diff --git a/packages/core/src/js/version.ts b/packages/core/src/js/version.ts index e67dc5efc7..116de554fb 100644 --- a/packages/core/src/js/version.ts +++ b/packages/core/src/js/version.ts @@ -1,3 +1,3 @@ export const SDK_PACKAGE_NAME = 'npm:@sentry/react-native'; export const SDK_NAME = 'sentry.javascript.react-native'; -export const SDK_VERSION = '6.4.0-beta.1'; +export const SDK_VERSION = '6.4.0'; diff --git a/performance-tests/TestAppPlain/package.json b/performance-tests/TestAppPlain/package.json index 0435d98a0b..4a92a49348 100644 --- a/performance-tests/TestAppPlain/package.json +++ b/performance-tests/TestAppPlain/package.json @@ -1,6 +1,6 @@ { "name": "TestAppPlain", - "version": "6.4.0-beta.1", + "version": "6.4.0", "private": true, "scripts": { "android": "react-native run-android", diff --git a/performance-tests/TestAppSentry/package.json b/performance-tests/TestAppSentry/package.json index 115b308673..8062005765 100644 --- a/performance-tests/TestAppSentry/package.json +++ b/performance-tests/TestAppSentry/package.json @@ -1,6 +1,6 @@ { "name": "TestAppSentry", - "version": "6.4.0-beta.1", + "version": "6.4.0", "private": true, "scripts": { "android": "react-native run-android", @@ -8,7 +8,7 @@ "start": "react-native start" }, "dependencies": { - "@sentry/react-native": "6.4.0-beta.1", + "@sentry/react-native": "6.4.0", "react": "18.1.0", "react-native": "0.70.6" }, diff --git a/samples/expo/app.json b/samples/expo/app.json index d1d6870567..e90dfc9204 100644 --- a/samples/expo/app.json +++ b/samples/expo/app.json @@ -4,7 +4,7 @@ "slug": "sentry-react-native-expo-sample", "jsEngine": "hermes", "scheme": "sentry-expo-sample", - "version": "6.4.0-beta.1", + "version": "6.4.0", "orientation": "portrait", "icon": "./assets/icon.png", "userInterfaceStyle": "light", @@ -19,7 +19,7 @@ "ios": { "supportsTablet": true, "bundleIdentifier": "io.sentry.expo.sample", - "buildNumber": "33" + "buildNumber": "34" }, "android": { "adaptiveIcon": { @@ -27,7 +27,7 @@ "backgroundColor": "#ffffff" }, "package": "io.sentry.expo.sample", - "versionCode": 33 + "versionCode": 34 }, "web": { "bundler": "metro", diff --git a/samples/expo/package.json b/samples/expo/package.json index a25ec3bf3a..2a0f9eca92 100644 --- a/samples/expo/package.json +++ b/samples/expo/package.json @@ -1,6 +1,6 @@ { "name": "sentry-react-native-expo-sample", - "version": "6.4.0-beta.1", + "version": "6.4.0", "main": "expo-router/entry", "scripts": { "start": "expo start", @@ -16,7 +16,7 @@ "set-version": "npx react-native-version --skip-tag --never-amend" }, "dependencies": { - "@sentry/react-native": "6.4.0-beta.1", + "@sentry/react-native": "6.4.0", "@types/react": "~18.3.12", "expo": "^52.0.0", "expo-constants": "~17.0.3", diff --git a/samples/react-native-macos/package.json b/samples/react-native-macos/package.json index 0c21ef7ce7..f840cfc382 100644 --- a/samples/react-native-macos/package.json +++ b/samples/react-native-macos/package.json @@ -1,6 +1,6 @@ { "name": "sentry-react-native-macos-sample", - "version": "6.4.0-beta.1", + "version": "6.4.0", "private": true, "scripts": { "start": "react-native start --experimental-debugger", @@ -17,7 +17,7 @@ "@react-navigation/native": "^6.1.9", "@react-navigation/stack": "^6.3.20", "@sentry/react": "8.40.0", - "@sentry/react-native": "6.4.0-beta.1", + "@sentry/react-native": "6.4.0", "@sentry/types": "8.40.0", "@sentry/utils": "8.40.0", "delay": "^6.0.0", diff --git a/samples/react-native/android/app/build.gradle b/samples/react-native/android/app/build.gradle index ced667a4e5..320cda26f0 100644 --- a/samples/react-native/android/app/build.gradle +++ b/samples/react-native/android/app/build.gradle @@ -136,8 +136,8 @@ android { applicationId "io.sentry.reactnative.sample" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 35 - versionName "6.4.0-beta.1" + versionCode 36 + versionName "6.4.0" } signingConfigs { diff --git a/samples/react-native/ios/sentryreactnativesample/Info.plist b/samples/react-native/ios/sentryreactnativesample/Info.plist index e27b1fea42..5ad873ca8e 100644 --- a/samples/react-native/ios/sentryreactnativesample/Info.plist +++ b/samples/react-native/ios/sentryreactnativesample/Info.plist @@ -21,7 +21,7 @@ CFBundleSignature ???? CFBundleVersion - 40 + 41 LSRequiresIPhoneOS NSAppTransportSecurity diff --git a/samples/react-native/ios/sentryreactnativesampleTests/Info.plist b/samples/react-native/ios/sentryreactnativesampleTests/Info.plist index 2ded0b77c6..028b4ca8da 100644 --- a/samples/react-native/ios/sentryreactnativesampleTests/Info.plist +++ b/samples/react-native/ios/sentryreactnativesampleTests/Info.plist @@ -19,6 +19,6 @@ CFBundleSignature ???? CFBundleVersion - 40 + 41 diff --git a/samples/react-native/package.json b/samples/react-native/package.json index 4788f733ca..4c0069d099 100644 --- a/samples/react-native/package.json +++ b/samples/react-native/package.json @@ -1,6 +1,6 @@ { "name": "sentry-react-native-sample", - "version": "6.4.0-beta.1", + "version": "6.4.0", "private": true, "scripts": { "postinstall": "patch-package", @@ -25,7 +25,7 @@ "@react-navigation/native": "^7.0.3", "@react-navigation/native-stack": "^7.0.3", "@react-navigation/stack": "^7.0.3", - "@sentry/react-native": "6.4.0-beta.1", + "@sentry/react-native": "6.4.0", "delay": "^6.0.0", "react": "18.3.1", "react-native": "0.76.3", diff --git a/yarn.lock b/yarn.lock index 30025ea02e..2a809dbccd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7818,7 +7818,7 @@ __metadata: languageName: node linkType: hard -"@sentry/react-native@6.4.0-beta.1, @sentry/react-native@workspace:packages/core": +"@sentry/react-native@6.4.0, @sentry/react-native@workspace:packages/core": version: 0.0.0-use.local resolution: "@sentry/react-native@workspace:packages/core" dependencies: @@ -9493,7 +9493,7 @@ __metadata: dependencies: "@babel/core": ^7.12.9 "@babel/runtime": ^7.12.5 - "@sentry/react-native": 6.4.0-beta.1 + "@sentry/react-native": 6.4.0 metro-react-native-babel-preset: ^0.72.3 react: 18.1.0 react-native: 0.70.6 @@ -24294,7 +24294,7 @@ __metadata: dependencies: "@babel/preset-env": ^7.25.3 "@babel/preset-typescript": ^7.18.6 - "@sentry/react-native": 6.4.0-beta.1 + "@sentry/react-native": 6.4.0 "@sentry/utils": 8.40.0 "@types/node": ^20.9.3 "@types/react": ^18.2.64 @@ -24324,7 +24324,7 @@ __metadata: "@babel/core": ^7.26.0 "@babel/preset-env": ^7.26.0 "@sentry/babel-plugin-component-annotate": ^2.18.0 - "@sentry/react-native": 6.4.0-beta.1 + "@sentry/react-native": 6.4.0 "@types/node": 20.10.4 "@types/react": ~18.3.12 expo: ^52.0.0 @@ -24359,7 +24359,7 @@ __metadata: "@react-navigation/native": ^6.1.9 "@react-navigation/stack": ^6.3.20 "@sentry/react": 8.40.0 - "@sentry/react-native": 6.4.0-beta.1 + "@sentry/react-native": 6.4.0 "@sentry/types": 8.40.0 "@sentry/utils": 8.40.0 "@types/react": ^18.2.65 @@ -24406,7 +24406,7 @@ __metadata: "@react-navigation/native-stack": ^7.0.3 "@react-navigation/stack": ^7.0.3 "@sentry/babel-plugin-component-annotate": ^2.18.0 - "@sentry/react-native": 6.4.0-beta.1 + "@sentry/react-native": 6.4.0 "@types/react": ^18.2.65 "@types/react-native-vector-icons": ^6.4.18 "@types/react-test-renderer": ^18.0.0 From 4fa81ce5ea53e0eaa171c15dcda7c6c27b17bc2a Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 10 Dec 2024 16:09:21 +0200 Subject: [PATCH 09/28] Close screen before sending the feedback to minimise wait time Co-authored-by: LucasZF --- packages/core/src/js/feedback/FeedbackForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index ba6be6712a..d103675916 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -62,8 +62,8 @@ export class FeedbackForm extends React.Component Date: Tue, 10 Dec 2024 16:27:29 +0200 Subject: [PATCH 10/28] Rename file for consistency --- packages/core/src/js/feedback/FeedbackForm.tsx | 2 +- .../core/src/js/feedback/{FeedbackForm.types.ts => config.ts} | 0 packages/core/test/feedback/FeedbackForm.test.tsx | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename packages/core/src/js/feedback/{FeedbackForm.types.ts => config.ts} (100%) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index d103675916..8585da1f46 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -19,7 +19,7 @@ import { NAME_PLACEHOLDER, SUBMIT_BUTTON_LABEL} from './constants'; import defaultStyles from './FeedbackForm.styles'; -import type { FeedbackFormProps, FeedbackFormState } from './FeedbackForm.types'; +import type { FeedbackFormProps, FeedbackFormState } from './config'; import LabelText from './LabelText'; /** diff --git a/packages/core/src/js/feedback/FeedbackForm.types.ts b/packages/core/src/js/feedback/config.ts similarity index 100% rename from packages/core/src/js/feedback/FeedbackForm.types.ts rename to packages/core/src/js/feedback/config.ts diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index 4f26fab428..8887318fb1 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { Alert } from 'react-native'; import { FeedbackForm } from '../../src/js/feedback/FeedbackForm'; -import type { FeedbackFormProps } from '../../src/js/feedback/FeedbackForm.types'; +import type { FeedbackFormProps } from '../../src/js/feedback/config'; const mockCloseScreen = jest.fn(); From 0258bf2c0ac778b1178da01c7b13320a2966225a Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 10 Dec 2024 19:09:15 +0200 Subject: [PATCH 11/28] Flatten configuration hierarchy and clean up --- .../src/js/feedback/FeedbackForm.styles.ts | 6 +- .../core/src/js/feedback/FeedbackForm.tsx | 89 +++++++----------- .../src/js/feedback/FeedbackForm.types.ts | 94 +++++++++++++++++++ packages/core/src/js/feedback/LabelText.tsx | 21 ----- packages/core/src/js/feedback/config.ts | 41 -------- packages/core/src/js/feedback/constants.ts | 45 ++++++--- .../core/test/feedback/FeedbackForm.test.tsx | 73 +++++++------- samples/react-native/src/App.tsx | 2 +- 8 files changed, 205 insertions(+), 166 deletions(-) create mode 100644 packages/core/src/js/feedback/FeedbackForm.types.ts delete mode 100644 packages/core/src/js/feedback/LabelText.tsx delete mode 100644 packages/core/src/js/feedback/config.ts diff --git a/packages/core/src/js/feedback/FeedbackForm.styles.ts b/packages/core/src/js/feedback/FeedbackForm.styles.ts index 88dbfd52c8..d54fb9cd83 100644 --- a/packages/core/src/js/feedback/FeedbackForm.styles.ts +++ b/packages/core/src/js/feedback/FeedbackForm.styles.ts @@ -1,6 +1,6 @@ -import { StyleSheet } from 'react-native'; +import type { FeedbackFormStyles } from './FeedbackForm.types'; -const defaultStyles = StyleSheet.create({ +const defaultStyles: FeedbackFormStyles = { container: { flex: 1, padding: 20, @@ -49,6 +49,6 @@ const defaultStyles = StyleSheet.create({ color: '#6a1b9a', fontSize: 16, }, -}); +}; export default defaultStyles; diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 8585da1f46..3b68bab6b2 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -4,23 +4,9 @@ import * as React from 'react'; import type { KeyboardTypeOptions } from 'react-native'; import { Alert, Text, TextInput, TouchableOpacity, View } from 'react-native'; -import { - CANCEL_BUTTON_LABEL, - EMAIL_ERROR, - EMAIL_LABEL, - EMAIL_PLACEHOLDER, - ERROR_TITLE, - FORM_ERROR, - FORM_TITLE, - IS_REQUIRED_LABEL, - MESSAGE_LABEL, - MESSAGE_PLACEHOLDER, - NAME_LABEL, - NAME_PLACEHOLDER, - SUBMIT_BUTTON_LABEL} from './constants'; +import { defaultConfiguration } from './constants'; import defaultStyles from './FeedbackForm.styles'; -import type { FeedbackFormProps, FeedbackFormState } from './config'; -import LabelText from './LabelText'; +import type { FeedbackFormProps, FeedbackFormState, FeedbackFormStyles,FeedbackTextConfiguration } from './FeedbackForm.types'; /** * @beta @@ -38,21 +24,20 @@ export class FeedbackForm extends React.Component void = () => { const { name, email, description } = this.state; - const { closeScreen, text } = this.props; + const { closeScreen } = this.props; + const text: FeedbackTextConfiguration = { ...defaultConfiguration, ...this.props }; const trimmedName = name?.trim(); const trimmedEmail = email?.trim(); const trimmedDescription = description?.trim(); if (!trimmedName || !trimmedEmail || !trimmedDescription) { - const errorMessage = text?.formError || FORM_ERROR; - Alert.alert(text?.errorTitle || ERROR_TITLE, errorMessage); + Alert.alert(text.errorTitle, text.formError); return; } if (!this._isValidEmail(trimmedEmail)) { - const errorMessage = text?.emailError || EMAIL_ERROR; - Alert.alert(text?.errorTitle || ERROR_TITLE, errorMessage); + Alert.alert(text.errorTitle, text.emailError); return; } @@ -70,58 +55,56 @@ export class FeedbackForm extends React.Component - {text?.formTitle || FORM_TITLE} - - + + {text.formTitle} + + + {text.nameLabel} + {true && ` ${text.isRequiredLabel}`} + this.setState({ name: value })} /> - + + + {text.emailLabel} + {true && ` ${text.isRequiredLabel}`} + this.setState({ email: value })} /> - + + + {text.messageLabel} + {true && ` ${text.isRequiredLabel}`} + this.setState({ description: value })} multiline /> - - {text?.submitButton || SUBMIT_BUTTON_LABEL} + + {text.submitButtonLabel} - - {text?.cancelButton || CANCEL_BUTTON_LABEL} + + {text.cancelButtonLabel} ); diff --git a/packages/core/src/js/feedback/FeedbackForm.types.ts b/packages/core/src/js/feedback/FeedbackForm.types.ts new file mode 100644 index 0000000000..bfc958a4cf --- /dev/null +++ b/packages/core/src/js/feedback/FeedbackForm.types.ts @@ -0,0 +1,94 @@ +import type { TextStyle, ViewStyle } from 'react-native'; + +export interface FeedbackFormProps extends FeedbackTextConfiguration { + closeScreen: () => void; + styles?: FeedbackFormStyles; +} + +/** + * All of the different text labels that can be customized + */ +export interface FeedbackTextConfiguration { + /** + * The label for the Feedback form cancel button that closes dialog + */ + cancelButtonLabel?: string; + + /** + * The label for the Feedback form submit button that sends feedback + */ + submitButtonLabel?: string; + + /** + * The title of the Feedback form + */ + formTitle?: string; + + /** + * Label for the email input + */ + emailLabel?: string; + + /** + * Placeholder text for Feedback email input + */ + emailPlaceholder?: string; + + /** + * Label for the message input + */ + messageLabel?: string; + + /** + * Placeholder text for Feedback message input + */ + messagePlaceholder?: string; + + /** + * Label for the name input + */ + nameLabel?: string; + + /** + * Placeholder text for Feedback name input + */ + namePlaceholder?: string; + + /** + * Text which indicates that a field is required + */ + isRequiredLabel?: string; + + /** + * The title of the error dialog + */ + errorTitle?: string; + + /** + * The error message when the form is invalid + */ + formError?: string; + + /** + * The error message when the email is invalid + */ + emailError?: string; +} + +export interface FeedbackFormStyles { + container?: ViewStyle; + title?: TextStyle; + label?: TextStyle; + input?: TextStyle; + textArea?: TextStyle; + submitButton?: ViewStyle; + submitText?: TextStyle; + cancelButton?: ViewStyle; + cancelText?: TextStyle; +} + +export interface FeedbackFormState { + name: string; + email: string; + description: string; +} diff --git a/packages/core/src/js/feedback/LabelText.tsx b/packages/core/src/js/feedback/LabelText.tsx deleted file mode 100644 index a03c69b207..0000000000 --- a/packages/core/src/js/feedback/LabelText.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from 'react'; -import type { TextStyle } from 'react-native'; -import { Text } from 'react-native'; - -interface LabelTextProps { - label: string; - isRequired: boolean; - isRequiredLabel: string; - styles: TextStyle; -} - -const LabelText: React.FC = ({ label, isRequired, isRequiredLabel, styles }) => { - return ( - - {label} - {isRequired && ` ${isRequiredLabel}`} - - ); -}; - -export default LabelText; diff --git a/packages/core/src/js/feedback/config.ts b/packages/core/src/js/feedback/config.ts deleted file mode 100644 index 0316573f18..0000000000 --- a/packages/core/src/js/feedback/config.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { TextStyle, ViewStyle } from 'react-native'; - -export interface FeedbackFormProps { - closeScreen: () => void; - text: FeedbackFormText; - styles?: FeedbackFormStyles; -} - -export interface FeedbackFormText { - formTitle?: string; - nameLabel?: string; - namePlaceholder?: string; - emailLabel?: string; - emailPlaceholder?: string; - descriptionLabel?: string; - descriptionPlaceholder?: string; - isRequiredLabel?: string; - submitButton?: string; - cancelButton?: string; - errorTitle?: string; - formError?: string; - emailError?: string; -} - -export interface FeedbackFormStyles { - container?: ViewStyle; - title?: TextStyle; - label?: TextStyle; - input?: TextStyle; - textArea?: ViewStyle; - submitButton?: ViewStyle; - submitText?: TextStyle; - cancelButton?: ViewStyle; - cancelText?: TextStyle; -} - -export interface FeedbackFormState { - name: string; - email: string; - description: string; -} diff --git a/packages/core/src/js/feedback/constants.ts b/packages/core/src/js/feedback/constants.ts index c30d30122f..19df28885b 100644 --- a/packages/core/src/js/feedback/constants.ts +++ b/packages/core/src/js/feedback/constants.ts @@ -1,13 +1,32 @@ -export const FORM_TITLE = 'Report a Bug'; -export const NAME_PLACEHOLDER = 'Your Name'; -export const NAME_LABEL = 'Name'; -export const EMAIL_PLACEHOLDER = 'your.email@example.org'; -export const EMAIL_LABEL = 'Email'; -export const MESSAGE_PLACEHOLDER = "What's the bug? What did you expect?"; -export const MESSAGE_LABEL = 'Description'; -export const IS_REQUIRED_LABEL = '(required)'; -export const SUBMIT_BUTTON_LABEL = 'Send Bug Report'; -export const CANCEL_BUTTON_LABEL = 'Cancel'; -export const ERROR_TITLE = 'Error'; -export const FORM_ERROR = 'Please fill out all required fields.'; -export const EMAIL_ERROR = 'Please enter a valid email address.'; +import type { FeedbackFormProps } from './FeedbackForm.types'; + +const FORM_TITLE = 'Report a Bug'; +const NAME_PLACEHOLDER = 'Your Name'; +const NAME_LABEL = 'Name'; +const EMAIL_PLACEHOLDER = 'your.email@example.org'; +const EMAIL_LABEL = 'Email'; +const MESSAGE_PLACEHOLDER = "What's the bug? What did you expect?"; +const MESSAGE_LABEL = 'Description'; +const IS_REQUIRED_LABEL = '(required)'; +const SUBMIT_BUTTON_LABEL = 'Send Bug Report'; +const CANCEL_BUTTON_LABEL = 'Cancel'; +const ERROR_TITLE = 'Error'; +const FORM_ERROR = 'Please fill out all required fields.'; +const EMAIL_ERROR = 'Please enter a valid email address.'; + +export const defaultConfiguration: Partial = { + // FeedbackTextConfiguration + cancelButtonLabel: CANCEL_BUTTON_LABEL, + emailLabel: EMAIL_LABEL, + emailPlaceholder: EMAIL_PLACEHOLDER, + formTitle: FORM_TITLE, + isRequiredLabel: IS_REQUIRED_LABEL, + messageLabel: MESSAGE_LABEL, + messagePlaceholder: MESSAGE_PLACEHOLDER, + nameLabel: NAME_LABEL, + namePlaceholder: NAME_PLACEHOLDER, + submitButtonLabel: SUBMIT_BUTTON_LABEL, + errorTitle: ERROR_TITLE, + formError: FORM_ERROR, + emailError: EMAIL_ERROR, +}; diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index 8887318fb1..b930c0afc0 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { Alert } from 'react-native'; import { FeedbackForm } from '../../src/js/feedback/FeedbackForm'; -import type { FeedbackFormProps } from '../../src/js/feedback/config'; +import type { FeedbackFormProps } from '../../src/js/feedback/FeedbackForm.types'; const mockCloseScreen = jest.fn(); @@ -16,17 +16,19 @@ jest.mock('@sentry/core', () => ({ const defaultProps: FeedbackFormProps = { closeScreen: mockCloseScreen, - text: { - formTitle: 'Feedback Form', - namePlaceholder: 'Name', - emailPlaceholder: 'Email', - descriptionPlaceholder: 'Description', - submitButton: 'Submit', - cancelButton: 'Cancel', - errorTitle: 'Error', - formError: 'Please fill out all required fields.', - emailError: 'The email address is not valid.', - }, + formTitle: 'Feedback Form', + nameLabel: 'Name', + namePlaceholder: 'Name Placeholder', + emailLabel: 'Email', + emailPlaceholder: 'Email Placeholder', + messageLabel: 'Description', + messagePlaceholder: 'Description Placeholder', + submitButtonLabel: 'Submit', + cancelButtonLabel: 'Cancel', + isRequiredLabel: '(required)', + errorTitle: 'Error', + formError: 'Please fill out all required fields.', + emailError: 'The email address is not valid.', }; describe('FeedbackForm', () => { @@ -37,46 +39,49 @@ describe('FeedbackForm', () => { it('renders correctly', () => { const { getByPlaceholderText, getByText } = render(); - expect(getByText(defaultProps.text.formTitle)).toBeTruthy(); - expect(getByPlaceholderText(defaultProps.text.namePlaceholder)).toBeTruthy(); - expect(getByPlaceholderText(defaultProps.text.emailPlaceholder)).toBeTruthy(); - expect(getByPlaceholderText(defaultProps.text.descriptionPlaceholder)).toBeTruthy(); - expect(getByText(defaultProps.text.submitButton)).toBeTruthy(); - expect(getByText(defaultProps.text.cancelButton)).toBeTruthy(); + expect(getByText(defaultProps.formTitle)).toBeTruthy(); + expect(getByText(`${defaultProps.nameLabel } ${ defaultProps.isRequiredLabel}`)).toBeTruthy(); + expect(getByPlaceholderText(defaultProps.namePlaceholder)).toBeTruthy(); + expect(getByText(`${defaultProps.emailLabel } ${ defaultProps.isRequiredLabel}`)).toBeTruthy(); + expect(getByPlaceholderText(defaultProps.emailPlaceholder)).toBeTruthy(); + expect(getByText(`${defaultProps.messageLabel } ${ defaultProps.isRequiredLabel}`)).toBeTruthy(); + expect(getByPlaceholderText(defaultProps.messagePlaceholder)).toBeTruthy(); + expect(getByText(defaultProps.submitButtonLabel)).toBeTruthy(); + expect(getByText(defaultProps.cancelButtonLabel)).toBeTruthy(); }); it('shows an error message if required fields are empty', async () => { const { getByText } = render(); - fireEvent.press(getByText(defaultProps.text.submitButton)); + fireEvent.press(getByText(defaultProps.submitButtonLabel)); await waitFor(() => { - expect(Alert.alert).toHaveBeenCalledWith(defaultProps.text.errorTitle, defaultProps.text.formError); + expect(Alert.alert).toHaveBeenCalledWith(defaultProps.errorTitle, defaultProps.formError); }); }); it('shows an error message if the email is not valid', async () => { const { getByPlaceholderText, getByText } = render(); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.namePlaceholder), 'John Doe'); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.emailPlaceholder), 'not-an-email'); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.descriptionPlaceholder), 'This is a feedback message.'); + fireEvent.changeText(getByPlaceholderText(defaultProps.namePlaceholder), 'John Doe'); + fireEvent.changeText(getByPlaceholderText(defaultProps.emailPlaceholder), 'not-an-email'); + fireEvent.changeText(getByPlaceholderText(defaultProps.messagePlaceholder), 'This is a feedback message.'); - fireEvent.press(getByText(defaultProps.text.submitButton)); + fireEvent.press(getByText(defaultProps.submitButtonLabel)); await waitFor(() => { - expect(Alert.alert).toHaveBeenCalledWith(defaultProps.text.errorTitle, defaultProps.text.emailError); + expect(Alert.alert).toHaveBeenCalledWith(defaultProps.errorTitle, defaultProps.emailError); }); }); it('calls captureFeedback when the form is submitted successfully', async () => { const { getByPlaceholderText, getByText } = render(); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.namePlaceholder), 'John Doe'); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.emailPlaceholder), 'john.doe@example.com'); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.descriptionPlaceholder), 'This is a feedback message.'); + fireEvent.changeText(getByPlaceholderText(defaultProps.namePlaceholder), 'John Doe'); + fireEvent.changeText(getByPlaceholderText(defaultProps.emailPlaceholder), 'john.doe@example.com'); + fireEvent.changeText(getByPlaceholderText(defaultProps.messagePlaceholder), 'This is a feedback message.'); - fireEvent.press(getByText(defaultProps.text.submitButton)); + fireEvent.press(getByText(defaultProps.submitButtonLabel)); await waitFor(() => { expect(captureFeedback).toHaveBeenCalledWith({ @@ -90,11 +95,11 @@ describe('FeedbackForm', () => { it('calls closeScreen when the form is submitted successfully', async () => { const { getByPlaceholderText, getByText } = render(); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.namePlaceholder), 'John Doe'); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.emailPlaceholder), 'john.doe@example.com'); - fireEvent.changeText(getByPlaceholderText(defaultProps.text.descriptionPlaceholder), 'This is a feedback message.'); + fireEvent.changeText(getByPlaceholderText(defaultProps.namePlaceholder), 'John Doe'); + fireEvent.changeText(getByPlaceholderText(defaultProps.emailPlaceholder), 'john.doe@example.com'); + fireEvent.changeText(getByPlaceholderText(defaultProps.messagePlaceholder), 'This is a feedback message.'); - fireEvent.press(getByText(defaultProps.text.submitButton)); + fireEvent.press(getByText(defaultProps.submitButtonLabel)); await waitFor(() => { expect(mockCloseScreen).toHaveBeenCalled(); @@ -104,7 +109,7 @@ describe('FeedbackForm', () => { it('calls closeScreen when the cancel button is pressed', () => { const { getByText } = render(); - fireEvent.press(getByText(defaultProps.text.cancelButton)); + fireEvent.press(getByText(defaultProps.cancelButtonLabel)); expect(mockCloseScreen).toHaveBeenCalled(); }); diff --git a/samples/react-native/src/App.tsx b/samples/react-native/src/App.tsx index cd2656edcf..054a1ad6ce 100644 --- a/samples/react-native/src/App.tsx +++ b/samples/react-native/src/App.tsx @@ -169,7 +169,7 @@ const ErrorsTabNavigator = Sentry.withProfiler( marginBottom: 10, }, }} - text={{namePlaceholder: 'Fullname'}} + namePlaceholder={'Fullname'} /> )} From 458ebc2afd2a75b95be1b8a16973ee508e6b5a1a Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 10 Dec 2024 19:44:51 +0200 Subject: [PATCH 12/28] Align required values with JS --- .../core/src/js/feedback/FeedbackForm.tsx | 14 +++++----- .../src/js/feedback/FeedbackForm.types.ts | 27 ++++++++++++++++++- packages/core/src/js/feedback/constants.ts | 6 +++++ .../core/test/feedback/FeedbackForm.test.tsx | 9 ++++--- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 3b68bab6b2..2f9fde5501 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -6,7 +6,7 @@ import { Alert, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { defaultConfiguration } from './constants'; import defaultStyles from './FeedbackForm.styles'; -import type { FeedbackFormProps, FeedbackFormState, FeedbackFormStyles,FeedbackTextConfiguration } from './FeedbackForm.types'; +import type { FeedbackFormProps, FeedbackFormState, FeedbackFormStyles,FeedbackGeneralConfiguration, FeedbackTextConfiguration } from './FeedbackForm.types'; /** * @beta @@ -25,18 +25,19 @@ export class FeedbackForm extends React.Component void = () => { const { name, email, description } = this.state; const { closeScreen } = this.props; + const config: FeedbackGeneralConfiguration = { ...defaultConfiguration, ...this.props }; const text: FeedbackTextConfiguration = { ...defaultConfiguration, ...this.props }; const trimmedName = name?.trim(); const trimmedEmail = email?.trim(); const trimmedDescription = description?.trim(); - if (!trimmedName || !trimmedEmail || !trimmedDescription) { + if ((config.isNameRequired && !trimmedName) || (config.isEmailRequired && !trimmedEmail) || !trimmedDescription) { Alert.alert(text.errorTitle, text.formError); return; } - if (!this._isValidEmail(trimmedEmail)) { + if (config.isEmailRequired && !this._isValidEmail(trimmedEmail)) { Alert.alert(text.errorTitle, text.emailError); return; } @@ -57,6 +58,7 @@ export class FeedbackForm extends React.Component {text.nameLabel} - {true && ` ${text.isRequiredLabel}`} + {config.isNameRequired && ` ${text.isRequiredLabel}`} {text.emailLabel} - {true && ` ${text.isRequiredLabel}`} + {config.isEmailRequired && ` ${text.isRequiredLabel}`} {text.messageLabel} - {true && ` ${text.isRequiredLabel}`} + {` ${text.isRequiredLabel}`} void; styles?: FeedbackFormStyles; } +/** + * General feedback configuration + */ +export interface FeedbackGeneralConfiguration { + /** + * Should the email field be required? + */ + isEmailRequired?: boolean; + + /** + * Should the name field be required? + */ + isNameRequired?: boolean; + + /** + * Should the email input field be visible? Note: email will still be collected if set via `Sentry.setUser()` + */ + showEmail?: boolean; + + /** + * Should the name input field be visible? Note: name will still be collected if set via `Sentry.setUser()` + */ + showName?: boolean; +} + /** * All of the different text labels that can be customized */ diff --git a/packages/core/src/js/feedback/constants.ts b/packages/core/src/js/feedback/constants.ts index 19df28885b..5272c7a86c 100644 --- a/packages/core/src/js/feedback/constants.ts +++ b/packages/core/src/js/feedback/constants.ts @@ -15,6 +15,12 @@ const FORM_ERROR = 'Please fill out all required fields.'; const EMAIL_ERROR = 'Please enter a valid email address.'; export const defaultConfiguration: Partial = { + // FeedbackGeneralConfiguration + isEmailRequired: false, + isNameRequired: false, + showEmail: true, + showName: true, + // FeedbackTextConfiguration cancelButtonLabel: CANCEL_BUTTON_LABEL, emailLabel: EMAIL_LABEL, diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index b930c0afc0..8b309418fe 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -40,9 +40,9 @@ describe('FeedbackForm', () => { const { getByPlaceholderText, getByText } = render(); expect(getByText(defaultProps.formTitle)).toBeTruthy(); - expect(getByText(`${defaultProps.nameLabel } ${ defaultProps.isRequiredLabel}`)).toBeTruthy(); + expect(getByText(defaultProps.nameLabel)).toBeTruthy(); expect(getByPlaceholderText(defaultProps.namePlaceholder)).toBeTruthy(); - expect(getByText(`${defaultProps.emailLabel } ${ defaultProps.isRequiredLabel}`)).toBeTruthy(); + expect(getByText(defaultProps.emailLabel)).toBeTruthy(); expect(getByPlaceholderText(defaultProps.emailPlaceholder)).toBeTruthy(); expect(getByText(`${defaultProps.messageLabel } ${ defaultProps.isRequiredLabel}`)).toBeTruthy(); expect(getByPlaceholderText(defaultProps.messagePlaceholder)).toBeTruthy(); @@ -60,8 +60,9 @@ describe('FeedbackForm', () => { }); }); - it('shows an error message if the email is not valid', async () => { - const { getByPlaceholderText, getByText } = render(); + it('shows an error message if the email is not valid and the email is required', async () => { + const withEmailProps = {...defaultProps, ...{isEmailRequired: true}}; + const { getByPlaceholderText, getByText } = render(); fireEvent.changeText(getByPlaceholderText(defaultProps.namePlaceholder), 'John Doe'); fireEvent.changeText(getByPlaceholderText(defaultProps.emailPlaceholder), 'not-an-email'); From f0e1befe7700d8673883304f84a0f7c936c7b77c Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 10 Dec 2024 20:22:29 +0200 Subject: [PATCH 13/28] Use Sentry user email and name when set --- packages/core/src/js/feedback/FeedbackForm.tsx | 8 +++++--- .../core/src/js/feedback/FeedbackForm.types.ts | 9 +++++++++ .../js/feedback/{constants.ts => defaults.ts} | 6 ++++++ .../core/test/feedback/FeedbackForm.test.tsx | 16 ++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) rename packages/core/src/js/feedback/{constants.ts => defaults.ts} (87%) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 2f9fde5501..20dc8d37b4 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import type { KeyboardTypeOptions } from 'react-native'; import { Alert, Text, TextInput, TouchableOpacity, View } from 'react-native'; -import { defaultConfiguration } from './constants'; +import { defaultConfiguration } from './defaults'; import defaultStyles from './FeedbackForm.styles'; import type { FeedbackFormProps, FeedbackFormState, FeedbackFormStyles,FeedbackGeneralConfiguration, FeedbackTextConfiguration } from './FeedbackForm.types'; @@ -15,9 +15,11 @@ import type { FeedbackFormProps, FeedbackFormState, FeedbackFormStyles,FeedbackG export class FeedbackForm extends React.Component { public constructor(props: FeedbackFormProps) { super(props); + + const config: FeedbackGeneralConfiguration = { ...defaultConfiguration, ...props }; this.state = { - name: '', - email: '', + name: config.useSentryUser.name, + email: config.useSentryUser.email, description: '', }; } diff --git a/packages/core/src/js/feedback/FeedbackForm.types.ts b/packages/core/src/js/feedback/FeedbackForm.types.ts index 637f9c4274..146cf3f534 100644 --- a/packages/core/src/js/feedback/FeedbackForm.types.ts +++ b/packages/core/src/js/feedback/FeedbackForm.types.ts @@ -28,6 +28,15 @@ export interface FeedbackGeneralConfiguration { * Should the name input field be visible? Note: name will still be collected if set via `Sentry.setUser()` */ showName?: boolean; + + /** + * Fill in email/name input fields with Sentry user context if it exists. + * The value of the email/name keys represent the properties of your user context. + */ + useSentryUser?: { + email: string; + name: string; + }; } /** diff --git a/packages/core/src/js/feedback/constants.ts b/packages/core/src/js/feedback/defaults.ts similarity index 87% rename from packages/core/src/js/feedback/constants.ts rename to packages/core/src/js/feedback/defaults.ts index 5272c7a86c..ae210212d6 100644 --- a/packages/core/src/js/feedback/constants.ts +++ b/packages/core/src/js/feedback/defaults.ts @@ -1,3 +1,5 @@ +import { getCurrentScope } from '@sentry/core'; + import type { FeedbackFormProps } from './FeedbackForm.types'; const FORM_TITLE = 'Report a Bug'; @@ -20,6 +22,10 @@ export const defaultConfiguration: Partial = { isNameRequired: false, showEmail: true, showName: true, + useSentryUser: { + email: getCurrentScope().getUser().email || '', + name: getCurrentScope().getUser().name || '', + }, // FeedbackTextConfiguration cancelButtonLabel: CANCEL_BUTTON_LABEL, diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index 8b309418fe..10b1f41c37 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -12,6 +12,12 @@ jest.spyOn(Alert, 'alert'); jest.mock('@sentry/core', () => ({ captureFeedback: jest.fn(), + getCurrentScope: jest.fn(() => ({ + getUser: jest.fn(() => ({ + email: 'test@example.com', + name: 'Test User', + })), + })), })); const defaultProps: FeedbackFormProps = { @@ -50,6 +56,16 @@ describe('FeedbackForm', () => { expect(getByText(defaultProps.cancelButtonLabel)).toBeTruthy(); }); + it('name and email are prefilled when sentry user is set', () => { + const { getByPlaceholderText } = render(); + + const nameInput = getByPlaceholderText(defaultProps.namePlaceholder); + const emailInput = getByPlaceholderText(defaultProps.emailPlaceholder); + + expect(nameInput.props.value).toBe('Test User'); + expect(emailInput.props.value).toBe('test@example.com'); + }); + it('shows an error message if required fields are empty', async () => { const { getByText } = render(); From b9235f2b07cc3bf0cadf9046e0373a15f5594c8b Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 10 Dec 2024 20:41:07 +0200 Subject: [PATCH 14/28] Simplifies email validation --- packages/core/src/js/feedback/FeedbackForm.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 20dc8d37b4..84b9f3c9cc 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -39,7 +39,7 @@ export class FeedbackForm extends React.Component 0) && !this._isValidEmail(trimmedEmail)) { Alert.alert(text.errorTitle, text.emailError); return; } @@ -115,7 +115,7 @@ export class FeedbackForm extends React.Component { - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ return emailRegex.test(email); }; } From 9385d74e04969875ca82c1aa773c11128c1024fe Mon Sep 17 00:00:00 2001 From: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Date: Wed, 11 Dec 2024 09:23:19 +0100 Subject: [PATCH 15/28] fix(ios): Disable HTTP Client errors in sentry-cocoa to avoid duplicates (#4347) --- CHANGELOG.md | 1 + .../RNSentryCocoaTesterTests/RNSentryTests.mm | 16 ++++++++++++++++ packages/core/ios/RNSentry.mm | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94e8f03e90..7bf0372f0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ - Return `lastEventId` export from `@sentry/core` ([#4315](https://github.com/getsentry/sentry-react-native/pull/4315)) - Don't log file not found errors when loading envs in `sentry-expo-upload-sourcemaps` ([#4332](https://github.com/getsentry/sentry-react-native/pull/4332)) - Navigation Span should have no parent by default ([#4326](https://github.com/getsentry/sentry-react-native/pull/4326)) +- Disable HTTP Client Errors on iOS ([#4347](https://github.com/getsentry/sentry-react-native/pull/4347)) ### Dependencies diff --git a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryTests.mm b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryTests.mm index df720ee1af..6e63793b85 100644 --- a/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryTests.mm +++ b/packages/core/RNSentryCocoaTester/RNSentryCocoaTesterTests/RNSentryTests.mm @@ -38,6 +38,22 @@ - (void)testCreateOptionsWithDictionaryRemovesPerformanceProperties XCTAssertEqual(actualOptions.enableTracing, false, @"EnableTracing should not be passed to native"); } +- (void)testCaptureFailedRequestsIsDisabled +{ + RNSentry *rnSentry = [[RNSentry alloc] init]; + NSError *error = nil; + + NSDictionary *_Nonnull mockedReactNativeDictionary = @{ + @"dsn" : @"https://abcd@efgh.ingest.sentry.io/123456", + }; + SentryOptions *actualOptions = [rnSentry createOptionsWithDictionary:mockedReactNativeDictionary + error:&error]; + + XCTAssertNotNil(actualOptions, @"Did not create sentry options"); + XCTAssertNil(error, @"Should not pass no error"); + XCTAssertFalse(actualOptions.enableCaptureFailedRequests); +} + - (void)testCreateOptionsWithDictionaryNativeCrashHandlingDefault { RNSentry *rnSentry = [[RNSentry alloc] init]; diff --git a/packages/core/ios/RNSentry.mm b/packages/core/ios/RNSentry.mm index ab22df9ec8..fc4091d220 100644 --- a/packages/core/ios/RNSentry.mm +++ b/packages/core/ios/RNSentry.mm @@ -215,7 +215,7 @@ - (SentryOptions *_Nullable)createOptionsWithDictionary:(NSDictionary *_Nonnull) } // Failed requests can only be enabled in one SDK to avoid duplicates - sentryOptions.enableCaptureFailedRequests = @NO; + sentryOptions.enableCaptureFailedRequests = NO; return sentryOptions; } From 39a67bd9ee34ef95abcb247021e32526e01821ff Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 11:34:21 +0200 Subject: [PATCH 16/28] Show success alert message --- packages/core/src/js/feedback/FeedbackForm.tsx | 1 + .../core/src/js/feedback/FeedbackForm.types.ts | 5 +++++ packages/core/src/js/feedback/defaults.ts | 2 ++ packages/core/test/feedback/FeedbackForm.test.tsx | 15 +++++++++++++++ 4 files changed, 23 insertions(+) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 84b9f3c9cc..d99d1da13d 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -52,6 +52,7 @@ export class FeedbackForm extends React.Component = { // FeedbackGeneralConfiguration @@ -41,4 +42,5 @@ export const defaultConfiguration: Partial = { errorTitle: ERROR_TITLE, formError: FORM_ERROR, emailError: EMAIL_ERROR, + successMessageText: SUCCESS_MESSAGE_TEXT, }; diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index 10b1f41c37..7809959000 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -35,6 +35,7 @@ const defaultProps: FeedbackFormProps = { errorTitle: 'Error', formError: 'Please fill out all required fields.', emailError: 'The email address is not valid.', + successMessageText: 'Feedback success', }; describe('FeedbackForm', () => { @@ -109,6 +110,20 @@ describe('FeedbackForm', () => { }); }); + it('shows success message when the form is submitted successfully', async () => { + const { getByPlaceholderText, getByText } = render(); + + fireEvent.changeText(getByPlaceholderText(defaultProps.namePlaceholder), 'John Doe'); + fireEvent.changeText(getByPlaceholderText(defaultProps.emailPlaceholder), 'john.doe@example.com'); + fireEvent.changeText(getByPlaceholderText(defaultProps.messagePlaceholder), 'This is a feedback message.'); + + fireEvent.press(getByText(defaultProps.submitButtonLabel)); + + await waitFor(() => { + expect(Alert.alert).toHaveBeenCalledWith(defaultProps.successMessageText); + }); + }); + it('calls closeScreen when the form is submitted successfully', async () => { const { getByPlaceholderText, getByText } = render(); From 501a134fea6f6188abf4672e2aa8a67e640b05b1 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 12:26:08 +0200 Subject: [PATCH 17/28] Aligns naming with JS and unmounts the form by default --- .../core/src/js/feedback/FeedbackForm.tsx | 19 +++++++++++++++---- .../src/js/feedback/FeedbackForm.types.ts | 14 ++++++++++++-- packages/core/src/js/feedback/defaults.ts | 5 +++++ .../core/test/feedback/FeedbackForm.test.tsx | 12 ++++++------ samples/react-native/src/App.tsx | 2 +- 5 files changed, 39 insertions(+), 13 deletions(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index d99d1da13d..bea617b3d9 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -18,6 +18,7 @@ export class FeedbackForm extends React.Component void = () => { const { name, email, description } = this.state; - const { closeScreen } = this.props; + const { onFormClose } = { ...defaultConfiguration, ...this.props }; const config: FeedbackGeneralConfiguration = { ...defaultConfiguration, ...this.props }; const text: FeedbackTextConfiguration = { ...defaultConfiguration, ...this.props }; @@ -50,7 +51,9 @@ export class FeedbackForm extends React.Component { + onFormClose(); + this.setState({ isVisible: false }); + } + + if (!this.state.isVisible) { + return null; + } return ( @@ -108,7 +119,7 @@ export class FeedbackForm extends React.Component{text.submitButtonLabel} - + {text.cancelButtonLabel} diff --git a/packages/core/src/js/feedback/FeedbackForm.types.ts b/packages/core/src/js/feedback/FeedbackForm.types.ts index 8d2d076a4f..aac7a1e1be 100644 --- a/packages/core/src/js/feedback/FeedbackForm.types.ts +++ b/packages/core/src/js/feedback/FeedbackForm.types.ts @@ -1,7 +1,6 @@ import type { TextStyle, ViewStyle } from 'react-native'; -export interface FeedbackFormProps extends FeedbackGeneralConfiguration, FeedbackTextConfiguration { - closeScreen: () => void; +export interface FeedbackFormProps extends FeedbackGeneralConfiguration, FeedbackTextConfiguration, FeedbackCallbacks { styles?: FeedbackFormStyles; } @@ -114,6 +113,16 @@ export interface FeedbackTextConfiguration { emailError?: string; } +/** + * The public callbacks available for the feedback integration + */ +export interface FeedbackCallbacks { + /** + * Callback when form is closed and not submitted + */ + onFormClose?: () => void; +} + export interface FeedbackFormStyles { container?: ViewStyle; title?: TextStyle; @@ -127,6 +136,7 @@ export interface FeedbackFormStyles { } export interface FeedbackFormState { + isVisible: boolean; name: string; email: string; description: string; diff --git a/packages/core/src/js/feedback/defaults.ts b/packages/core/src/js/feedback/defaults.ts index 91d9a32d12..daca7c4f70 100644 --- a/packages/core/src/js/feedback/defaults.ts +++ b/packages/core/src/js/feedback/defaults.ts @@ -18,6 +18,11 @@ const EMAIL_ERROR = 'Please enter a valid email address.'; const SUCCESS_MESSAGE_TEXT = 'Thank you for your report!'; export const defaultConfiguration: Partial = { + // FeedbackCallbacks + onFormClose: () => { + // By default the form is just unmounted + }, + // FeedbackGeneralConfiguration isEmailRequired: false, isNameRequired: false, diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index 7809959000..de7ed90d04 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -6,7 +6,7 @@ import { Alert } from 'react-native'; import { FeedbackForm } from '../../src/js/feedback/FeedbackForm'; import type { FeedbackFormProps } from '../../src/js/feedback/FeedbackForm.types'; -const mockCloseScreen = jest.fn(); +const mockOnFormClose = jest.fn(); jest.spyOn(Alert, 'alert'); @@ -21,7 +21,7 @@ jest.mock('@sentry/core', () => ({ })); const defaultProps: FeedbackFormProps = { - closeScreen: mockCloseScreen, + onFormClose: mockOnFormClose, formTitle: 'Feedback Form', nameLabel: 'Name', namePlaceholder: 'Name Placeholder', @@ -124,7 +124,7 @@ describe('FeedbackForm', () => { }); }); - it('calls closeScreen when the form is submitted successfully', async () => { + it('calls onFormClose when the form is submitted successfully', async () => { const { getByPlaceholderText, getByText } = render(); fireEvent.changeText(getByPlaceholderText(defaultProps.namePlaceholder), 'John Doe'); @@ -134,15 +134,15 @@ describe('FeedbackForm', () => { fireEvent.press(getByText(defaultProps.submitButtonLabel)); await waitFor(() => { - expect(mockCloseScreen).toHaveBeenCalled(); + expect(mockOnFormClose).toHaveBeenCalled(); }); }); - it('calls closeScreen when the cancel button is pressed', () => { + it('calls onFormClose when the cancel button is pressed', () => { const { getByText } = render(); fireEvent.press(getByText(defaultProps.cancelButtonLabel)); - expect(mockCloseScreen).toHaveBeenCalled(); + expect(mockOnFormClose).toHaveBeenCalled(); }); }); diff --git a/samples/react-native/src/App.tsx b/samples/react-native/src/App.tsx index 054a1ad6ce..0e3f0285a8 100644 --- a/samples/react-native/src/App.tsx +++ b/samples/react-native/src/App.tsx @@ -159,7 +159,7 @@ const ErrorsTabNavigator = Sentry.withProfiler( {(props) => ( Date: Wed, 11 Dec 2024 12:38:04 +0200 Subject: [PATCH 18/28] Use the minimum config without props in the changelog --- CHANGELOG.md | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41a552cc1d..4b113ff7e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,20 +41,7 @@ ```jsx import { FeedbackForm } from "@sentry/react-native"; ... - + ``` Check [the documentation](https://docs.sentry.io/platforms/react-native/user-feedback/) for more configuration options. From 7109deb3a233891f06c7ac89a87d069bb669139d Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 12:47:44 +0200 Subject: [PATCH 19/28] Adds development not for unimplemented function --- packages/core/src/js/feedback/defaults.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/core/src/js/feedback/defaults.ts b/packages/core/src/js/feedback/defaults.ts index daca7c4f70..5b0360ec47 100644 --- a/packages/core/src/js/feedback/defaults.ts +++ b/packages/core/src/js/feedback/defaults.ts @@ -1,4 +1,5 @@ import { getCurrentScope } from '@sentry/core'; +import { Alert } from 'react-native'; import type { FeedbackFormProps } from './FeedbackForm.types'; @@ -20,7 +21,12 @@ const SUCCESS_MESSAGE_TEXT = 'Thank you for your report!'; export const defaultConfiguration: Partial = { // FeedbackCallbacks onFormClose: () => { - // By default the form is just unmounted + if (__DEV__) { + Alert.alert( + 'Development note', + 'onFormClose callback is not implemented. By default the form is just unmounted.', + ); + } }, // FeedbackGeneralConfiguration From c80c5cbf99941e952dfeb6676bd30abaef99762c Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 13:12:46 +0200 Subject: [PATCH 20/28] Show email and name conditionally --- .../core/src/js/feedback/FeedbackForm.tsx | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index bea617b3d9..6bd8ca3cff 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -80,28 +80,36 @@ export class FeedbackForm extends React.Component {text.formTitle} - + {config.showName && ( + <> + {text.nameLabel} {config.isNameRequired && ` ${text.isRequiredLabel}`} - - this.setState({ name: value })} + + this.setState({ name: value })} /> + + )} - + {config.showEmail && ( + <> + {text.emailLabel} {config.isEmailRequired && ` ${text.isRequiredLabel}`} - - this.setState({ email: value })} + + this.setState({ email: value })} /> + + )} {text.messageLabel} From 8c5675351db5dce4f3b0981d9005e748fc66da89 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 14:14:49 +0200 Subject: [PATCH 21/28] Adds sentry branding (png logo) --- .../src/js/feedback/FeedbackForm.styles.ts | 11 ++++++++++- packages/core/src/js/feedback/FeedbackForm.tsx | 9 +++++++-- .../core/src/js/feedback/FeedbackForm.types.ts | 18 +++++++++++++++++- packages/core/src/js/feedback/defaults.ts | 1 + .../core/test/feedback/FeedbackForm.test.tsx | 1 + 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.styles.ts b/packages/core/src/js/feedback/FeedbackForm.styles.ts index d54fb9cd83..c3bb293051 100644 --- a/packages/core/src/js/feedback/FeedbackForm.styles.ts +++ b/packages/core/src/js/feedback/FeedbackForm.styles.ts @@ -10,7 +10,8 @@ const defaultStyles: FeedbackFormStyles = { fontSize: 24, fontWeight: 'bold', marginBottom: 20, - textAlign: 'center', + textAlign: 'left', + flex: 1, }, label: { marginBottom: 4, @@ -49,6 +50,14 @@ const defaultStyles: FeedbackFormStyles = { color: '#6a1b9a', fontSize: 16, }, + titleContainer: { + flexDirection: 'row', + width: '100%', + }, + sentryLogo: { + width: 40, + height: 40, + }, }; export default defaultStyles; diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 6bd8ca3cff..1259c19e6c 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -2,7 +2,7 @@ import { captureFeedback } from '@sentry/core'; import type { SendFeedbackParams } from '@sentry/types'; import * as React from 'react'; import type { KeyboardTypeOptions } from 'react-native'; -import { Alert, Text, TextInput, TouchableOpacity, View } from 'react-native'; +import { Alert, Image, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { defaultConfiguration } from './defaults'; import defaultStyles from './FeedbackForm.styles'; @@ -78,7 +78,12 @@ export class FeedbackForm extends React.Component - {text.formTitle} + + {text.formTitle} + {config.showBranding && ( + + )} + {config.showName && ( <> diff --git a/packages/core/src/js/feedback/FeedbackForm.types.ts b/packages/core/src/js/feedback/FeedbackForm.types.ts index aac7a1e1be..7a900f3d49 100644 --- a/packages/core/src/js/feedback/FeedbackForm.types.ts +++ b/packages/core/src/js/feedback/FeedbackForm.types.ts @@ -1,5 +1,8 @@ -import type { TextStyle, ViewStyle } from 'react-native'; +import type { ImageStyle, TextStyle, ViewStyle } from 'react-native'; +/** + * The props for the feedback form + */ export interface FeedbackFormProps extends FeedbackGeneralConfiguration, FeedbackTextConfiguration, FeedbackCallbacks { styles?: FeedbackFormStyles; } @@ -8,6 +11,11 @@ export interface FeedbackFormProps extends FeedbackGeneralConfiguration, Feedbac * General feedback configuration */ export interface FeedbackGeneralConfiguration { + /** + * Show the Sentry branding + */ + showBranding?: boolean; + /** * Should the email field be required? */ @@ -123,6 +131,9 @@ export interface FeedbackCallbacks { onFormClose?: () => void; } +/** + * The styles for the feedback form + */ export interface FeedbackFormStyles { container?: ViewStyle; title?: TextStyle; @@ -133,8 +144,13 @@ export interface FeedbackFormStyles { submitText?: TextStyle; cancelButton?: ViewStyle; cancelText?: TextStyle; + titleContainer?: ViewStyle; + sentryLogo?: ImageStyle; } +/** + * The state of the feedback form + */ export interface FeedbackFormState { isVisible: boolean; name: string; diff --git a/packages/core/src/js/feedback/defaults.ts b/packages/core/src/js/feedback/defaults.ts index 5b0360ec47..94a5036512 100644 --- a/packages/core/src/js/feedback/defaults.ts +++ b/packages/core/src/js/feedback/defaults.ts @@ -30,6 +30,7 @@ export const defaultConfiguration: Partial = { }, // FeedbackGeneralConfiguration + showBranding: true, isEmailRequired: false, isNameRequired: false, showEmail: true, diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index de7ed90d04..a088216fcb 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -36,6 +36,7 @@ const defaultProps: FeedbackFormProps = { formError: 'Please fill out all required fields.', emailError: 'The email address is not valid.', successMessageText: 'Feedback success', + showBranding: false, }; describe('FeedbackForm', () => { From d6e9229430c70808d2f30279cc0f63e7daab0a82 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 14:20:57 +0200 Subject: [PATCH 22/28] Adds sentry logo resource --- packages/core/assets/sentrylogo.png | Bin 0 -> 3476 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 packages/core/assets/sentrylogo.png diff --git a/packages/core/assets/sentrylogo.png b/packages/core/assets/sentrylogo.png new file mode 100644 index 0000000000000000000000000000000000000000..610c3e0ff0ae9cf4e8075bd17570270458c0c2a4 GIT binary patch literal 3476 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 literal 0 HcmV?d00001 From 529247542a10e501e18b76e53e2933c7772d2d06 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 15:37:23 +0200 Subject: [PATCH 23/28] Add assets in module exports --- packages/core/react-native.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/core/react-native.config.js b/packages/core/react-native.config.js index d307073e1a..fe07b4e15a 100644 --- a/packages/core/react-native.config.js +++ b/packages/core/react-native.config.js @@ -7,5 +7,6 @@ module.exports = { packageImportPath: 'import io.sentry.react.RNSentryPackage;' } } - } + }, + assets: ['./assets/'], }; From efd809f6f03a92b659653faeaad6516d5d1a18fc Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 16:36:21 +0200 Subject: [PATCH 24/28] Revert "Add assets in module exports" This reverts commit 529247542a10e501e18b76e53e2933c7772d2d06. --- packages/core/react-native.config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/core/react-native.config.js b/packages/core/react-native.config.js index fe07b4e15a..d307073e1a 100644 --- a/packages/core/react-native.config.js +++ b/packages/core/react-native.config.js @@ -7,6 +7,5 @@ module.exports = { packageImportPath: 'import io.sentry.react.RNSentryPackage;' } } - }, - assets: ['./assets/'], + } }; From bc7ae659b1f825ada1c5e3ec2aea8ad7a6e7c233 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 16:36:35 +0200 Subject: [PATCH 25/28] Revert "Adds sentry logo resource" This reverts commit d6e9229430c70808d2f30279cc0f63e7daab0a82. --- packages/core/assets/sentrylogo.png | Bin 3476 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 packages/core/assets/sentrylogo.png diff --git a/packages/core/assets/sentrylogo.png b/packages/core/assets/sentrylogo.png deleted file mode 100644 index 610c3e0ff0ae9cf4e8075bd17570270458c0c2a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3476 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 From 79ee5ba69c7e752556089754f96c31e6690b5f32 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 16:36:45 +0200 Subject: [PATCH 26/28] Revert "Adds sentry branding (png logo)" This reverts commit 8c5675351db5dce4f3b0981d9005e748fc66da89. --- .../src/js/feedback/FeedbackForm.styles.ts | 11 +---------- packages/core/src/js/feedback/FeedbackForm.tsx | 9 ++------- .../core/src/js/feedback/FeedbackForm.types.ts | 18 +----------------- packages/core/src/js/feedback/defaults.ts | 1 - .../core/test/feedback/FeedbackForm.test.tsx | 1 - 5 files changed, 4 insertions(+), 36 deletions(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.styles.ts b/packages/core/src/js/feedback/FeedbackForm.styles.ts index c3bb293051..d54fb9cd83 100644 --- a/packages/core/src/js/feedback/FeedbackForm.styles.ts +++ b/packages/core/src/js/feedback/FeedbackForm.styles.ts @@ -10,8 +10,7 @@ const defaultStyles: FeedbackFormStyles = { fontSize: 24, fontWeight: 'bold', marginBottom: 20, - textAlign: 'left', - flex: 1, + textAlign: 'center', }, label: { marginBottom: 4, @@ -50,14 +49,6 @@ const defaultStyles: FeedbackFormStyles = { color: '#6a1b9a', fontSize: 16, }, - titleContainer: { - flexDirection: 'row', - width: '100%', - }, - sentryLogo: { - width: 40, - height: 40, - }, }; export default defaultStyles; diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 1259c19e6c..6bd8ca3cff 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -2,7 +2,7 @@ import { captureFeedback } from '@sentry/core'; import type { SendFeedbackParams } from '@sentry/types'; import * as React from 'react'; import type { KeyboardTypeOptions } from 'react-native'; -import { Alert, Image, Text, TextInput, TouchableOpacity, View } from 'react-native'; +import { Alert, Text, TextInput, TouchableOpacity, View } from 'react-native'; import { defaultConfiguration } from './defaults'; import defaultStyles from './FeedbackForm.styles'; @@ -78,12 +78,7 @@ export class FeedbackForm extends React.Component - - {text.formTitle} - {config.showBranding && ( - - )} - + {text.formTitle} {config.showName && ( <> diff --git a/packages/core/src/js/feedback/FeedbackForm.types.ts b/packages/core/src/js/feedback/FeedbackForm.types.ts index 7a900f3d49..aac7a1e1be 100644 --- a/packages/core/src/js/feedback/FeedbackForm.types.ts +++ b/packages/core/src/js/feedback/FeedbackForm.types.ts @@ -1,8 +1,5 @@ -import type { ImageStyle, TextStyle, ViewStyle } from 'react-native'; +import type { TextStyle, ViewStyle } from 'react-native'; -/** - * The props for the feedback form - */ export interface FeedbackFormProps extends FeedbackGeneralConfiguration, FeedbackTextConfiguration, FeedbackCallbacks { styles?: FeedbackFormStyles; } @@ -11,11 +8,6 @@ export interface FeedbackFormProps extends FeedbackGeneralConfiguration, Feedbac * General feedback configuration */ export interface FeedbackGeneralConfiguration { - /** - * Show the Sentry branding - */ - showBranding?: boolean; - /** * Should the email field be required? */ @@ -131,9 +123,6 @@ export interface FeedbackCallbacks { onFormClose?: () => void; } -/** - * The styles for the feedback form - */ export interface FeedbackFormStyles { container?: ViewStyle; title?: TextStyle; @@ -144,13 +133,8 @@ export interface FeedbackFormStyles { submitText?: TextStyle; cancelButton?: ViewStyle; cancelText?: TextStyle; - titleContainer?: ViewStyle; - sentryLogo?: ImageStyle; } -/** - * The state of the feedback form - */ export interface FeedbackFormState { isVisible: boolean; name: string; diff --git a/packages/core/src/js/feedback/defaults.ts b/packages/core/src/js/feedback/defaults.ts index 94a5036512..5b0360ec47 100644 --- a/packages/core/src/js/feedback/defaults.ts +++ b/packages/core/src/js/feedback/defaults.ts @@ -30,7 +30,6 @@ export const defaultConfiguration: Partial = { }, // FeedbackGeneralConfiguration - showBranding: true, isEmailRequired: false, isNameRequired: false, showEmail: true, diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index a088216fcb..de7ed90d04 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -36,7 +36,6 @@ const defaultProps: FeedbackFormProps = { formError: 'Please fill out all required fields.', emailError: 'The email address is not valid.', successMessageText: 'Feedback success', - showBranding: false, }; describe('FeedbackForm', () => { From ba13320d5ade1db589b223277ed3ffa813746f19 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 11 Dec 2024 17:29:40 +0200 Subject: [PATCH 27/28] Add last event id --- packages/core/src/js/feedback/FeedbackForm.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/src/js/feedback/FeedbackForm.tsx b/packages/core/src/js/feedback/FeedbackForm.tsx index 6bd8ca3cff..b79fe7935b 100644 --- a/packages/core/src/js/feedback/FeedbackForm.tsx +++ b/packages/core/src/js/feedback/FeedbackForm.tsx @@ -1,4 +1,4 @@ -import { captureFeedback } from '@sentry/core'; +import { captureFeedback, lastEventId } from '@sentry/core'; import type { SendFeedbackParams } from '@sentry/types'; import * as React from 'react'; import type { KeyboardTypeOptions } from 'react-native'; @@ -45,10 +45,12 @@ export class FeedbackForm extends React.Component Date: Wed, 11 Dec 2024 19:01:45 +0200 Subject: [PATCH 28/28] Mock lastEventId --- packages/core/test/feedback/FeedbackForm.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/core/test/feedback/FeedbackForm.test.tsx b/packages/core/test/feedback/FeedbackForm.test.tsx index de7ed90d04..272072f413 100644 --- a/packages/core/test/feedback/FeedbackForm.test.tsx +++ b/packages/core/test/feedback/FeedbackForm.test.tsx @@ -18,6 +18,7 @@ jest.mock('@sentry/core', () => ({ name: 'Test User', })), })), + lastEventId: jest.fn(), })); const defaultProps: FeedbackFormProps = {