Repository: getsentry/sentry-react-native
Pull request #4714: feat(feedback): Screenshot button
Author: login: antonis
Created: 2025-03-31T16:27:28Z | Merged: 2025-04-14T13:24:17Z

## :loudspeaker: Type of change
<!--- Put an `x` in the boxes that apply -->
- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring

**Based on [feat(feedback): Theming](https://github.com/getsentry/sentry-react-native/pull/4677)**

PR Chain:
- [feat(feedback): Report a Bug button](https://github.com/getsentry/sentry-react-native/pull/4378)
- [feat(feedback): Theming](https://github.com/getsentry/sentry-react-native/pull/4677)
- 👉 [feat(feedback): Screenshot button](https://github.com/getsentry/sentry-react-native/pull/4714)
- [ref(feedback): Extracts FeedbackWidgetProvider in a separate file](https://github.com/getsentry/sentry-react-native/pull/4718)
- [fix(feedback): Fixes accessibility issue on iOS](https://github.com/getsentry/sentry-react-native/pull/4739)
- [test(e2e): Adds Feedback Widget Maestro E2E tests](https://github.com/getsentry/sentry-react-native/pull/4604)

## :scroll: Description
<!--- Describe your changes in detail -->
- Adds `take screenshot button` in the feedback widget that:
  - closes the feedback modal
  - shows the `screenshot button`
- Adds `screenshot button` that captures a screenshot and opens the feedback widget modal with the captured screenshot as attachment

⚠️ Note that the screenshot button is not supported on the web because the `captureScreenshot()` function is only available on mobile. Support for web environment will be investigated on a separate PR.

https://github.com/user-attachments/assets/cfbd6b13-4c52-4537-9160-fcfff0262eda

### Feedback widget UI states 
| `enableScreenshot` (or `imagePicker` set) | `enableTakeScreenshot` |
|---|---|
|![Simulator Screenshot - iPhone 16e - 2025-04-07 at 18 17 59](https://github.com/user-attachments/assets/5f577011-afc7-493a-9532-b61698e1a310)|![Simulator Screenshot - iPhone 16e - 2025-04-07 at 18 20 05](https://github.com/user-attachments/assets/fbb829d1-61c6-471f-9f47-33788c2f9d93)|

|Both|Screenshot attached|
|---|---|
|![Simulator Screenshot - iPhone 16e - 2025-04-07 at 18 17 20](https://github.com/user-attachments/assets/9bd4def9-df49-45bd-bfbb-14c14840deaf)|![Simulator Screenshot - iPhone 16e - 2025-04-07 at 18 17 28](https://github.com/user-attachments/assets/b1cd4a5b-c347-4ca9-a728-1f26243d2f97)|

## :bulb: Motivation and Context
<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
Part of https://github.com/getsentry/sentry-react-native/issues/4302

## :green_heart: How did you test it?
Sample app

## :pencil: Checklist
<!--- Put an `x` in the boxes that apply -->
- [x] I added tests to verify changes
- [x] No new PII added or SDK only sends newly added PII if `sendDefaultPII` is enabled
- [ ] I updated the docs if needed.
- [x] I updated the wizard if needed.
- [x] All tests passing
- [x] No breaking changes

## :crystal_ball: Next steps



Diff:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 620d4fb35c..0f44788ff6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,6 +12,7 @@
 
 - Adds the `FeedbackButton` component that shows the Feedback Widget ([#4378](https://github.com/getsentry/sentry-react-native/pull/4378))
 - Add Feedback Widget theming ([#4677](https://github.com/getsentry/sentry-react-native/pull/4677))
+- Adds the `ScreenshotButton` component that takes a screenshot ([#4714](https://github.com/getsentry/sentry-react-native/issues/4714))
 
 ### Fixes
 
diff --git a/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java b/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java
index 8a6beaa024..28f0fcb45c 100644
--- a/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java
+++ b/packages/core/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java
@@ -20,6 +20,7 @@
 import com.facebook.react.bridge.Arguments;
 import com.facebook.react.bridge.Promise;
 import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReadableArray;
 import com.facebook.react.bridge.ReadableMap;
 import com.facebook.react.bridge.ReadableMapKeySetIterator;
 import com.facebook.react.bridge.ReadableType;
@@ -1027,6 +1028,15 @@ public void getDataFromUri(String uri, Promise promise) {
     }
   }
 
+  public void encodeToBase64(ReadableArray array, Promise promise) {
+    byte[] bytes = new byte[array.size()];
+    for (int i = 0; i < array.size(); i++) {
+      bytes[i] = (byte) array.getInt(i);
+    }
+    String base64String = android.util.Base64.encodeToString(bytes, android.util.Base64.DEFAULT);
+    promise.resolve(base64String);
+  }
+
   public void crashedLastRun(Promise promise) {
     promise.resolve(Sentry.isCrashedLastRun());
   }
diff --git a/packages/core/android/src/newarch/java/io/sentry/react/RNSentryModule.java b/packages/core/android/src/newarch/java/io/sentry/react/RNSentryModule.java
index 822ebc745c..5b14f05c92 100644
--- a/packages/core/android/src/newarch/java/io/sentry/react/RNSentryModule.java
+++ b/packages/core/android/src/newarch/java/io/sentry/react/RNSentryModule.java
@@ -183,6 +183,11 @@ public void getDataFromUri(String uri, Promise promise) {
     this.impl.getDataFromUri(uri, promise);
   }
 
+  @Override
+  public void encodeToBase64(ReadableArray array, Promise promise) {
+    this.impl.encodeToBase64(array, promise);
+  }
+
   @Override
   public void popTimeToDisplayFor(String key, Promise promise) {
     this.impl.popTimeToDisplayFor(key, promise);
diff --git a/packages/core/android/src/oldarch/java/io/sentry/react/RNSentryModule.java b/packages/core/android/src/oldarch/java/io/sentry/react/RNSentryModule.java
index e6c2ecce8c..780084932a 100644
--- a/packages/core/android/src/oldarch/java/io/sentry/react/RNSentryModule.java
+++ b/packages/core/android/src/oldarch/java/io/sentry/react/RNSentryModule.java
@@ -157,6 +157,11 @@ public void getDataFromUri(String uri, Promise promise) {
     this.impl.getDataFromUri(uri, promise);
   }
 
+  @ReactMethod
+  public void encodeToBase64(ReadableArray array, Promise promise) {
+    this.impl.encodeToBase64(array, promise);
+  }
+
   @ReactMethod(isBlockingSynchronousMethod = true)
   public WritableMap fetchNativeStackFramesBy(ReadableArray instructionsAddr) {
     // Not used on Android
diff --git a/packages/core/ios/RNSentry.mm b/packages/core/ios/RNSentry.mm
index 3afd510392..6b3070be11 100644
--- a/packages/core/ios/RNSentry.mm
+++ b/packages/core/ios/RNSentry.mm
@@ -970,4 +970,28 @@ + (SentryUser *_Nullable)userFrom:(NSDictionary *)userKeys
     return @YES; // The return ensures that the method is synchronous
 }
 
+RCT_EXPORT_METHOD(encodeToBase64
+                  : (NSArray *)array resolver
+                  : (RCTPromiseResolveBlock)resolve rejecter
+                  : (RCTPromiseRejectBlock)reject)
+{
+    NSUInteger count = array.count;
+    uint8_t *bytes = (uint8_t *)malloc(count);
+
+    if (!bytes) {
+        reject(@"encodeToBase64", @"Memory allocation failed", nil);
+        return;
+    }
+
+    for (NSUInteger i = 0; i < count; i++) {
+        bytes[i] = (uint8_t)[array[i] unsignedCharValue];
+    }
+
+    NSData *data = [NSData dataWithBytes:bytes length:count];
+    free(bytes);
+
+    NSString *base64String = [data base64EncodedStringWithOptions:0];
+    resolve(base64String);
+}
+
 @end
diff --git a/packages/core/src/js/NativeRNSentry.ts b/packages/core/src/js/NativeRNSentry.ts
index 638623a354..5b00b62116 100644
--- a/packages/core/src/js/NativeRNSentry.ts
+++ b/packages/core/src/js/NativeRNSentry.ts
@@ -51,6 +51,7 @@ export interface Spec extends TurboModule {
   getDataFromUri(uri: string): Promise<number[]>;
   popTimeToDisplayFor(key: string): Promise<number | undefined | null>;
   setActiveSpanId(spanId: string): boolean;
+  encodeToBase64(data: number[]): Promise<string | undefined | null>;
 }
 
 export type NativeStackFrame = {
diff --git a/packages/core/src/js/feedback/FeedbackWidget.styles.ts b/packages/core/src/js/feedback/FeedbackWidget.styles.ts
index 5feeff4957..94df799d21 100644
--- a/packages/core/src/js/feedback/FeedbackWidget.styles.ts
+++ b/packages/core/src/js/feedback/FeedbackWidget.styles.ts
@@ -63,6 +63,20 @@ const defaultStyles = (theme: FeedbackWidgetTheme): FeedbackWidgetStyles => {
       color: theme.foreground,
       fontSize: 16,
     },
+    takeScreenshotButton: {
+      backgroundColor: theme.background,
+      padding: 15,
+      borderRadius: 5,
+      alignItems: 'center',
+      borderWidth: 1,
+      borderColor: theme.border,
+      marginTop: -10,
+      marginBottom: 20,
+    },
+    takeScreenshotText: {
+      color: theme.foreground,
+      fontSize: 16,
+    },
     submitButton: {
       backgroundColor: theme.accentBackground,
       paddingVertical: 15,
@@ -132,6 +146,8 @@ export const defaultButtonStyles = (theme: FeedbackWidgetTheme): FeedbackButtonS
   };
 };
 
+export const defaultScreenshotButtonStyles = defaultButtonStyles;
+
 export const modalWrapper: ViewStyle = {
   position: 'absolute',
   top: 0,
diff --git a/packages/core/src/js/feedback/FeedbackWidget.tsx b/packages/core/src/js/feedback/FeedbackWidget.tsx
index a3d7e8489e..c1a687a688 100644
--- a/packages/core/src/js/feedback/FeedbackWidget.tsx
+++ b/packages/core/src/js/feedback/FeedbackWidget.tsx
@@ -1,3 +1,4 @@
+/* eslint-disable max-lines */
 import type { SendFeedbackParams } from '@sentry/core';
 import { captureFeedback, getCurrentScope, lastEventId, logger } from '@sentry/core';
 import * as React from 'react';
@@ -15,13 +16,15 @@ import {
 } from 'react-native';
 
 import { isWeb, notWeb } from '../utils/environment';
-import { getDataFromUri } from '../wrapper';
+import type { Screenshot } from '../wrapper';
+import { getDataFromUri, NATIVE } from '../wrapper';
 import { sentryLogo } from './branding';
 import { defaultConfiguration } from './defaults';
 import defaultStyles from './FeedbackWidget.styles';
 import { getTheme } from './FeedbackWidget.theme';
 import type { FeedbackGeneralConfiguration, FeedbackTextConfiguration, FeedbackWidgetProps, FeedbackWidgetState, FeedbackWidgetStyles, ImagePickerConfiguration } from './FeedbackWidget.types';
 import { lazyLoadFeedbackIntegration } from './lazy';
+import { getCapturedScreenshot } from './ScreenshotButton';
 import { base64ToUint8Array, feedbackAlertDialog, isValidEmail  } from './utils';
 
 /**
@@ -69,6 +72,20 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
     lazyLoadFeedbackIntegration();
   }
 
+  /**
+   * For testing purposes only.
+   */
+  public static reset(): void {
+    FeedbackWidget._savedState = {
+      name: '',
+      email: '',
+      description: '',
+      filename: undefined,
+      attachment: undefined,
+      attachmentUri: undefined,
+    };
+  }
+
   public handleFeedbackSubmit: () => void = () => {
     const { name, email, description } = this.state;
     const { onSubmitSuccess, onSubmitError, onFormSubmitted } = this.props;
@@ -123,7 +140,7 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
   };
 
   public onScreenshotButtonPress: () => void = async () => {
-    if (!this.state.filename && !this.state.attachment) {
+    if (!this._hasScreenshot()) {
       const imagePickerConfiguration: ImagePickerConfiguration = this.props;
       if (imagePickerConfiguration.imagePicker) {
         const launchImageLibrary = imagePickerConfiguration.imagePicker.launchImageLibraryAsync
@@ -238,6 +255,11 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
       return null;
     }
 
+    const screenshot = getCapturedScreenshot();
+    if (screenshot) {
+      this._setCapturedScreenshot(screenshot);
+    }
+
     return (
       <TouchableWithoutFeedback onPress={notWeb() ? Keyboard.dismiss: undefined}>
         <View style={styles.container}>
@@ -294,7 +316,7 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
             onChangeText={(value) => this.setState({ description: value })}
             multiline
           />
-          {(config.enableScreenshot || imagePickerConfiguration.imagePicker) && (
+          {(config.enableScreenshot || imagePickerConfiguration.imagePicker || this._hasScreenshot()) && (
             <View style={styles.screenshotContainer}>
               {this.state.attachmentUri && (
                 <Image
@@ -304,13 +326,24 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
               )}
               <TouchableOpacity style={styles.screenshotButton} onPress={this.onScreenshotButtonPress}>
                 <Text style={styles.screenshotText}>
-                  {!this.state.filename && !this.state.attachment
+                  {!this._hasScreenshot()
                     ? text.addScreenshotButtonLabel
                     : text.removeScreenshotButtonLabel}
                 </Text>
               </TouchableOpacity>
             </View>
           )}
+          {notWeb() && config.enableTakeScreenshot && !this.state.attachmentUri && (
+            <TouchableOpacity style={styles.takeScreenshotButton} onPress={() => {
+              // eslint-disable-next-line @typescript-eslint/no-var-requires
+              const { hideFeedbackButton, showScreenshotButton } = require('./FeedbackWidgetManager');
+              hideFeedbackButton();
+              onCancel();
+              showScreenshotButton();
+            }}>
+              <Text style={styles.takeScreenshotText}>{text.captureScreenshotButtonLabel}</Text>
+            </TouchableOpacity>
+          )}
           <TouchableOpacity style={styles.submitButton} onPress={this.handleFeedbackSubmit}>
             <Text style={styles.submitText}>{text.submitButtonLabel}</Text>
           </TouchableOpacity>
@@ -323,6 +356,24 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
     );
   }
 
+  private _setCapturedScreenshot = (screenshot: Screenshot): void => {
+    if (screenshot.data != null) {
+      logger.debug('Setting captured screenshot:', screenshot.filename);
+      NATIVE.encodeToBase64(screenshot.data).then((base64String) => {
+        if (base64String != null) {
+          const dataUri = `data:${screenshot.contentType};base64,${base64String}`;
+          this.setState({ filename: screenshot.filename, attachment: screenshot.data, attachmentUri: dataUri });
+        } else {
+          logger.error('Failed to read image data from:', screenshot.filename);
+        }
+      }).catch((error) => {
+        logger.error('Failed to read image data from:', screenshot.filename, 'error: ', error);
+      });
+    } else {
+      logger.error('Failed to read image data from:', screenshot.filename);
+    }
+  }
+
   private _saveFormState = (): void => {
     FeedbackWidget._savedState = { ...this.state };
   };
@@ -337,4 +388,8 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
       attachmentUri: undefined,
     };
   };
+
+  private _hasScreenshot = (): boolean => {
+    return this.state.filename !== undefined && this.state.attachment !== undefined && this.state.attachmentUri !== undefined;
+  }
 }
diff --git a/packages/core/src/js/feedback/FeedbackWidget.types.ts b/packages/core/src/js/feedback/FeedbackWidget.types.ts
index 68b09f7c4f..aaf03e8642 100644
--- a/packages/core/src/js/feedback/FeedbackWidget.types.ts
+++ b/packages/core/src/js/feedback/FeedbackWidget.types.ts
@@ -54,6 +54,12 @@ export interface FeedbackGeneralConfiguration {
    */
   enableScreenshot?: boolean;
 
+  /**
+   * This flag determines whether the "Take Screenshot" button is displayed
+   * @default false
+   */
+  enableTakeScreenshot?: 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.
@@ -124,15 +130,20 @@ export interface FeedbackTextConfiguration {
   isRequiredLabel?: string;
 
   /**
-   * The label for the button that adds a screenshot and renders the image editor
+   * The label for the button that adds a screenshot
    */
   addScreenshotButtonLabel?: string;
 
   /**
-   * The label for the button that removes a screenshot and hides the image editor
+   * The label for the button that removes a screenshot
    */
   removeScreenshotButtonLabel?: string;
 
+  /**
+   * The label for the button that shows the capture screenshot button
+   */
+  captureScreenshotButtonLabel?: string;
+
   /**
    * The title of the error dialog
    */
@@ -169,6 +180,21 @@ export interface FeedbackButtonTextConfiguration {
   triggerAriaLabel?: string;
 }
 
+/**
+ * The ScreenshotButton text labels that can be customized
+ */
+export interface ScreenshotButtonTextConfiguration {
+  /**
+   * The label for the Screenshot button
+   */
+  triggerLabel?: string;
+
+  /**
+   * The aria label for the Screenshot button
+   */
+  triggerAriaLabel?: string;
+}
+
 /**
  * The public callbacks available for the feedback integration
  */
@@ -258,6 +284,8 @@ export interface FeedbackWidgetStyles {
   screenshotContainer?: ViewStyle;
   screenshotThumbnail?: ImageStyle;
   screenshotText?: TextStyle;
+  takeScreenshotButton?: ViewStyle;
+  takeScreenshotText?: TextStyle;
   titleContainer?: ViewStyle;
   sentryLogo?: ImageStyle;
 }
@@ -278,6 +306,22 @@ export interface FeedbackButtonStyles {
   triggerIcon?: ImageStyle;
 }
 
+/**
+ * The props for the screenshot button
+ */
+export interface ScreenshotButtonProps extends ScreenshotButtonTextConfiguration {
+  styles?: ScreenshotButtonStyles;
+}
+
+/**
+ * The styles for the screenshot button
+ */
+export interface ScreenshotButtonStyles {
+  triggerButton?: ViewStyle;
+  triggerText?: TextStyle;
+  triggerIcon?: ImageStyle;
+}
+
 /**
  * The state of the feedback form
  */
diff --git a/packages/core/src/js/feedback/FeedbackWidgetManager.tsx b/packages/core/src/js/feedback/FeedbackWidgetManager.tsx
index 18224cab16..39c6d81839 100644
--- a/packages/core/src/js/feedback/FeedbackWidgetManager.tsx
+++ b/packages/core/src/js/feedback/FeedbackWidgetManager.tsx
@@ -3,14 +3,15 @@ import * as React from 'react';
 import type { NativeEventSubscription, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
 import { Animated, Appearance, Dimensions, Easing, Modal, PanResponder, Platform, ScrollView, View } from 'react-native';
 
-import { notWeb } from '../utils/environment';
+import { isWeb,notWeb  } from '../utils/environment';
 import { FeedbackButton } from './FeedbackButton';
 import { FeedbackWidget } from './FeedbackWidget';
 import { modalSheetContainer, modalWrapper, topSpacer } from './FeedbackWidget.styles';
 import { getTheme } from './FeedbackWidget.theme';
 import type { FeedbackWidgetStyles } from './FeedbackWidget.types';
-import { getFeedbackButtonOptions, getFeedbackOptions } from './integration';
-import { lazyLoadAutoInjectFeedbackButtonIntegration,lazyLoadAutoInjectFeedbackIntegration } from './lazy';
+import { getFeedbackButtonOptions, getFeedbackOptions, getScreenshotButtonOptions } from './integration';
+import { lazyLoadAutoInjectFeedbackButtonIntegration,lazyLoadAutoInjectFeedbackIntegration, lazyLoadAutoInjectScreenshotButtonIntegration } from './lazy';
+import { ScreenshotButton } from './ScreenshotButton';
 import { isModalSupported } from './utils';
 
 const PULL_DOWN_CLOSE_THRESHOLD = 200;
@@ -76,6 +77,12 @@ class FeedbackButtonManager extends FeedbackManager {
   }
 }
 
+class ScreenshotButtonManager extends FeedbackManager {
+  protected static get _feedbackComponentName(): string {
+    return 'ScreenshotButton';
+  }
+}
+
 interface FeedbackWidgetProviderProps {
   children: React.ReactNode;
   styles?: FeedbackWidgetStyles;
@@ -83,6 +90,7 @@ interface FeedbackWidgetProviderProps {
 
 interface FeedbackWidgetProviderState {
   isButtonVisible: boolean;
+  isScreenshotButtonVisible: boolean;
   isVisible: boolean;
   backgroundOpacity: Animated.Value;
   panY: Animated.Value;
@@ -92,6 +100,7 @@ interface FeedbackWidgetProviderState {
 class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps> {
   public state: FeedbackWidgetProviderState = {
     isButtonVisible: false,
+    isScreenshotButtonVisible: false,
     isVisible: false,
     backgroundOpacity: new Animated.Value(0),
     panY: new Animated.Value(Dimensions.get('screen').height),
@@ -135,6 +144,7 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
   public constructor(props: FeedbackWidgetProviderProps) {
     super(props);
     FeedbackButtonManager.initialize(this._setButtonVisibilityFunction);
+    ScreenshotButtonManager.initialize(this._setScreenshotButtonVisibilityFunction);
     FeedbackWidgetManager.initialize(this._setVisibilityFunction);
   }
 
@@ -193,7 +203,7 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
 
     const theme = getTheme();
 
-    const { isButtonVisible, isVisible, backgroundOpacity } = this.state;
+    const { isButtonVisible, isScreenshotButtonVisible, isVisible, backgroundOpacity } = this.state;
 
     const backgroundColor = backgroundOpacity.interpolate({
       inputRange: [0, 1],
@@ -205,7 +215,8 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
     return (
       <>
         {this.props.children}
-        {isButtonVisible && <FeedbackButton {...getFeedbackButtonOptions()}/>}
+        {isButtonVisible && <FeedbackButton {...getFeedbackButtonOptions()} />}
+        {isScreenshotButtonVisible && <ScreenshotButton {...getScreenshotButtonOptions()}/>}
         {isVisible &&
           <Animated.View style={[modalWrapper, { backgroundColor }]} >
             <Modal visible={isVisible} transparent animationType="none" onRequestClose={this._handleClose} testID="feedback-form-modal">
@@ -267,6 +278,10 @@ class FeedbackWidgetProvider extends React.Component<FeedbackWidgetProviderProps
     this.setState({ isButtonVisible: visible });
   };
 
+  private _setScreenshotButtonVisibilityFunction = (visible: boolean): void => {
+    this.setState({ isScreenshotButtonVisible: visible });
+  };
+
   private _handleClose = (): void => {
     FeedbackWidgetManager.hide();
   };
@@ -294,4 +309,21 @@ const resetFeedbackButtonManager = (): void => {
   FeedbackButtonManager.reset();
 };
 
-export { showFeedbackButton, hideFeedbackButton, showFeedbackWidget, FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager };
+const showScreenshotButton = (): void => {
+  if (isWeb()) {
+    logger.warn('ScreenshotButton is not supported on Web.');
+    return;
+  }
+  lazyLoadAutoInjectScreenshotButtonIntegration();
+  ScreenshotButtonManager.show();
+};
+
+const hideScreenshotButton = (): void => {
+  ScreenshotButtonManager.hide();
+};
+
+const resetScreenshotButtonManager = (): void => {
+  ScreenshotButtonManager.reset();
+};
+
+export { showFeedbackButton, hideFeedbackButton, showFeedbackWidget, showScreenshotButton, hideScreenshotButton, FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager };
diff --git a/packages/core/src/js/feedback/ScreenshotButton.tsx b/packages/core/src/js/feedback/ScreenshotButton.tsx
new file mode 100644
index 0000000000..105b2ab104
--- /dev/null
+++ b/packages/core/src/js/feedback/ScreenshotButton.tsx
@@ -0,0 +1,89 @@
+import * as React from 'react';
+import type { NativeEventSubscription} from 'react-native';
+import { Appearance, Image, Text, TouchableOpacity } from 'react-native';
+
+import type { Screenshot } from '../wrapper';
+import { NATIVE } from '../wrapper';
+import { defaultScreenshotButtonConfiguration } from './defaults';
+import { defaultScreenshotButtonStyles } from './FeedbackWidget.styles';
+import { getTheme } from './FeedbackWidget.theme';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles, ScreenshotButtonTextConfiguration } from './FeedbackWidget.types';
+import { hideScreenshotButton, showFeedbackWidget, showScreenshotButton } from './FeedbackWidgetManager';
+import { screenshotIcon } from './icons';
+import { lazyLoadFeedbackIntegration } from './lazy';
+
+let capturedScreenshot: Screenshot | undefined;
+
+const takeScreenshot = async (): Promise<void> => {
+  hideScreenshotButton();
+  setTimeout(async () => { // Delay capture to allow the button to hide
+    const screenshots: Screenshot[] | null = await NATIVE.captureScreenshot();
+    if (screenshots && screenshots.length > 0) {
+      capturedScreenshot = screenshots[0];
+      showFeedbackWidget();
+    } else {
+      showScreenshotButton();
+    }
+  }, 100);
+};
+
+export const getCapturedScreenshot = (): Screenshot | undefined => {
+  const screenshot = capturedScreenshot;
+  capturedScreenshot = undefined;
+  return screenshot;
+}
+
+/**
+ * @beta
+ * Implements a screenshot button that takes a screenshot.
+ */
+export class ScreenshotButton extends React.Component<ScreenshotButtonProps> {
+  private _themeListener: NativeEventSubscription;
+
+  public constructor(props: ScreenshotButtonProps) {
+    super(props);
+    lazyLoadFeedbackIntegration();
+  }
+
+  /**
+   * Adds a listener for theme changes.
+   */
+  public componentDidMount(): void {
+    this._themeListener = Appearance.addChangeListener(() => {
+      this.forceUpdate();
+    });
+  }
+
+  /**
+   * Removes the theme listener.
+   */
+  public componentWillUnmount(): void {
+    if (this._themeListener) {
+      this._themeListener.remove();
+    }
+  }
+
+  /**
+   * Renders the screenshot button.
+   */
+  public render(): React.ReactNode {
+    const theme = getTheme();
+    const text: ScreenshotButtonTextConfiguration = { ...defaultScreenshotButtonConfiguration, ...this.props };
+    const styles: ScreenshotButtonStyles = {
+      triggerButton: { ...defaultScreenshotButtonStyles(theme).triggerButton, ...this.props.styles?.triggerButton },
+      triggerText: { ...defaultScreenshotButtonStyles(theme).triggerText, ...this.props.styles?.triggerText },
+      triggerIcon: { ...defaultScreenshotButtonStyles(theme).triggerIcon, ...this.props.styles?.triggerIcon },
+    };
+
+    return (
+      <TouchableOpacity
+        style={styles.triggerButton}
+        onPress={ takeScreenshot }
+        accessibilityLabel={text.triggerAriaLabel}
+      >
+        <Image source={{ uri: screenshotIcon }} style={styles.triggerIcon}/>
+        <Text style={styles.triggerText}>{text.triggerLabel}</Text>
+      </TouchableOpacity>
+    );
+  }
+}
diff --git a/packages/core/src/js/feedback/defaults.ts b/packages/core/src/js/feedback/defaults.ts
index 0e60a49fb2..948d59c19b 100644
--- a/packages/core/src/js/feedback/defaults.ts
+++ b/packages/core/src/js/feedback/defaults.ts
@@ -1,4 +1,4 @@
-import type { FeedbackButtonProps, FeedbackWidgetProps } from './FeedbackWidget.types';
+import type { FeedbackButtonProps, FeedbackWidgetProps, ScreenshotButtonProps } from './FeedbackWidget.types';
 import { feedbackAlertDialog } from './utils';
 
 const FORM_TITLE = 'Report a Bug';
@@ -12,11 +12,13 @@ const IS_REQUIRED_LABEL = '(required)';
 const SUBMIT_BUTTON_LABEL = 'Send Bug Report';
 const CANCEL_BUTTON_LABEL = 'Cancel';
 const TRIGGER_LABEL = 'Report a Bug';
+const TRIGGER_SCREENSHOT_LABEL = 'Take Screenshot';
 const ERROR_TITLE = 'Error';
 const FORM_ERROR = 'Please fill out all required fields.';
 const EMAIL_ERROR = 'Please enter a valid email address.';
 const SUCCESS_MESSAGE_TEXT = 'Thank you for your report!';
 const ADD_SCREENSHOT_LABEL = 'Add a screenshot';
+const CAPTURE_SCREENSHOT_LABEL = 'Take a screenshot';
 const REMOVE_SCREENSHOT_LABEL = 'Remove screenshot';
 const GENERIC_ERROR_TEXT = 'Unable to send feedback due to an unexpected error.';
 
@@ -61,6 +63,7 @@ export const defaultConfiguration: Partial<FeedbackWidgetProps> = {
   showEmail: true,
   showName: true,
   enableScreenshot: false,
+  enableTakeScreenshot: false,
 
   // FeedbackTextConfiguration
   cancelButtonLabel: CANCEL_BUTTON_LABEL,
@@ -79,6 +82,7 @@ export const defaultConfiguration: Partial<FeedbackWidgetProps> = {
   successMessageText: SUCCESS_MESSAGE_TEXT,
   addScreenshotButtonLabel: ADD_SCREENSHOT_LABEL,
   removeScreenshotButtonLabel: REMOVE_SCREENSHOT_LABEL,
+  captureScreenshotButtonLabel: CAPTURE_SCREENSHOT_LABEL,
   genericError: GENERIC_ERROR_TEXT,
 };
 
@@ -86,3 +90,8 @@ export const defaultButtonConfiguration: Partial<FeedbackButtonProps> = {
   triggerLabel: TRIGGER_LABEL,
   triggerAriaLabel: '',
 };
+
+export const defaultScreenshotButtonConfiguration: Partial<ScreenshotButtonProps> = {
+  triggerLabel: TRIGGER_SCREENSHOT_LABEL,
+  triggerAriaLabel: '',
+};
diff --git a/packages/core/src/js/feedback/icons.ts b/packages/core/src/js/feedback/icons.ts
index 3404bf6347..b73ecdde86 100644
--- a/packages/core/src/js/feedback/icons.ts
+++ b/packages/core/src/js/feedback/icons.ts
@@ -1,2 +1,32 @@
 export const feedbackIcon =
   'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAMAAABrrFhUAAAAk1BMVEUAAAAqIDEqIjMmIDArIjIrIjMoHjErITMrIjMqITIqITIqITIqIjIqITIqITIhHi4qITIqITIeAConHi8rITMqITIqITIcHCopITIpIDEpIDIlGC8qITIqITIpIDIpHjAqITIqIDIqIDEqIDAqITInHjAqIDIqIDEqITIqITIqIDIiFCgpIDEqITIoHS8qIDIrIjMN1S0HAAAAMHRSTlMAhnknzMQy1zyF6/H55PYQ0rIGGPudjAmUTEQUv7p2K6lmWDZxHV9S36J+DD7bI208pRBPAAAGrUlEQVR42uzd6XLaMBSG4Y/YhuAVbAwx+xp2eu7/6tq0nfaHIAizSNbR+5vJJM8EG45lGfrm7EZRSNL5bvcAg1oM6fZaBQxp/0HlylOY0PuRyjbco/L1unRHbVS9RYPuaoxKlzY7dF9xhgpXb9Hd1VDddiHdX4SqNnHpIU1QzcYhPaY5qpjj0aNaooL9iOlhvaFynYZEnAFmAXEGWI2IOAN8BsQZIGsTcQaY+0SMAQZT+hVfgLVPX3EFSLb0J6YARUR/YwmQ5PQvjgD9DcmWJ7hUraoANwy9owIwDuCGofc2gXEANwy9/TVgHMANQ+/pAMYBpLUOSebPAeMAbhh6tzOYByA/9A4+AeMAbhh6j1YwD0B+6B3MAOMAbhh6D09QAdCvtT33ecUkWfwDeD1Ab+yTHnknKABYHEmPwjGgAKAISY/cCVQAvGvy94c7QAVAEpEWtepQA/BBOtRppngYwDaDfAMt3gCNBVAeQKzxUciC/iAN6vZwJ4BYsC0gU5uUd3wHHgAgFu0yXE39IfCjhwcBiHWmE1yJFLfpA+UBJJpOtAbI93gwgFieaQsQFcDzAShYagqwTfAUADF3oiGAvwZeBUDxUjuA6QBPBBAbDbQC8OfAawFoU9cIoJ3h5QAUz3UBCD4BBQBESz0ARisoAqCmBgDBDFAGQB/KAaYrqASgrlKAVtcB1ALQThJgXX94px4A5QD0KQfgQP/KAYQH5gDkZ8wByOMOQE3DAfJZHtF3dd7NBngDsKh9Z9BIjQf41dyjizU5AACHFl0odFgAADOfztdmAoBsROfrMwEAxh06l8cGAEVM5+qzAcDCpzMN+QBgEtCZ6nwAcAhJbMsIAHMSixNGAPggsRkngF6DhDxOAKiHJJRxAjj3JvjBCmAgngvbrACwE88DKSuARPxIfGAFgFx8JS+AungQ4AUAYUAUMQMQ79pNeAH0hZe+8wJIY+FKKS8AuMLFcmYAubBihBnAUliwwgxgLQwGmQEIpwGXGcBCWLXEDGAiXCZmBlDn/h9w4H4MKIS5KDOAmfB9mBmA8HUwZwYgLBaoMQOIhItDvAAccZEAL4Cl8NIVLwDhEBDwmgmKeyV4vADG4v0jvACO4m0hrAAKEspYAYjrZl1WV4c/SajGCWAfkdCCE0BOQhtOa4TWJNZlBLDySczhA5A0SMzjs1I0HdKZ5mwAem06U8RmtXji0bmWXACcBp3L7zEBuPQcpyWPW2ayKZ1vk3IASMcBXWjN4La5/exIlxqZf+fopBvQxeKT2QD7fvdI3zU2++7xgK40NHz/gGsFK+YABfMtNJrMd5GZQgpgE4RR47F50/FEPYDXU7qXmFsoBmglKAGg316KZQEaGcoBaLWZanmAVqZ8O72vtokiAC/RYEPFr6K+EoB2T48tNb/66L0eoKnRrrJEjcWLAYK1VvsKE3V2LwVwHd12lhZ+pzIA8toa7i1OFC9fBODW9dxdnmi4egGAP8M3dahMemwyLQUQ1BJ8l/KnrLUHzwQIatd+vEeq84unARyXCa7VJPXl+2cAxNM+JJqQBm0Ojwbwp+se5BqRDnXTBwK0xnXIV++QDrXqT7k2WJmnjRGFb88CqMgD94i8kyIAjEmP4pkiALy3SI9GmRoAoL/dkA75czUAXyUnx3HpfHPnWjmdz/nTW0iSTRMFAFc/GL+X/mVuf/J+1DcSAGn3hoGhiQDAYSM/MDQSAPv8hqfwmggArH35JwQaCYBBW35gaCQA8BnIDwyNBMBqKD8wNBIAWMbyA0MjATBx5QeGRgIgbXbkB4YmAgCLI91flQHQ+z+H4QkA9CP6E1cAJFP6HVsAYO7TrxgD/HkMEGcAYBYzB8DJYw4AvIXMAVBvMQdA2mUOABw2zAHEgWH5xpUEAAqfHtO8ogDCwLBsk6oCCAPDckWoLoAwMCxTt8oAwsDw9uJVtQHguPeeBCsOIAwMb2uEygMAiwaVbZiYAFB+YJinMAIAWAzp9loFYAoA4OxGUUjS+W73AJgEUCILYAEsgAWwABbAAlgAC2ABLIAFsAAWwAJYAAtgASyABbAAFsACWAALYAEsgAWwABbAAlgAC2ABLIAFsAAWwAKUANg2r+WZDSCRBbAAFsAC/GyfXlIYhIIgitYgGHhoiMmDSPyAgqKz2v/qxIkL0JoU9NlB3+6OABEgAkSACBABnAP0FMvwslGsgpeBYjW8FBQbYeZNqbKFmYlSDex0FEp2BwB8V8rkPwwViSJ5gaX5QYlkuf/DZ0i8rWwM///0m7bni5flqh5dxt8BPG/wrQSMUX8AAAAASUVORK5CYII=';
+
+/**
+ * Source: https://github.com/tabler/tabler-icons/blob/b54c86433ed5121e2590bf09f0faf746bb5aba66/icons/outline/screenshot.svg
+ *
+ * MIT License
+ *
+ * Copyright (c) 2020-2024 Paweł Kuna
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * TODO: Replace with another screenshot icon when available
+ */
+export const screenshotIcon =
+  'data:image/png;base64,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';
diff --git a/packages/core/src/js/feedback/integration.ts b/packages/core/src/js/feedback/integration.ts
index f6c2ebcba9..d450422aa3 100644
--- a/packages/core/src/js/feedback/integration.ts
+++ b/packages/core/src/js/feedback/integration.ts
@@ -1,13 +1,14 @@
 import { type Integration, getClient } from '@sentry/core';
 
 import type { FeedbackWidgetTheme } from './FeedbackWidget.theme';
-import type { FeedbackButtonProps, FeedbackWidgetProps } from './FeedbackWidget.types';
+import type { FeedbackButtonProps, FeedbackWidgetProps, ScreenshotButtonProps } from './FeedbackWidget.types';
 
 export const MOBILE_FEEDBACK_INTEGRATION_NAME = 'MobileFeedback';
 
 type FeedbackIntegration = Integration & {
   options: Partial<FeedbackWidgetProps>;
   buttonOptions: Partial<FeedbackButtonProps>;
+  screenshotButtonOptions: Partial<ScreenshotButtonProps>;
   colorScheme?: 'system' | 'light' | 'dark';
   themeLight: Partial<FeedbackWidgetTheme>;
   themeDark: Partial<FeedbackWidgetTheme>;
@@ -16,17 +17,26 @@ type FeedbackIntegration = Integration & {
 export const feedbackIntegration = (
   initOptions: FeedbackWidgetProps & {
     buttonOptions?: FeedbackButtonProps;
+    screenshotButtonOptions?: ScreenshotButtonProps;
     colorScheme?: 'system' | 'light' | 'dark';
     themeLight?: Partial<FeedbackWidgetTheme>;
     themeDark?: Partial<FeedbackWidgetTheme>;
   } = {},
 ): FeedbackIntegration => {
-  const { buttonOptions, colorScheme, themeLight: lightTheme, themeDark: darkTheme, ...widgetOptions } = initOptions;
+  const {
+    buttonOptions,
+    screenshotButtonOptions,
+    colorScheme,
+    themeLight: lightTheme,
+    themeDark: darkTheme,
+    ...widgetOptions
+  } = initOptions;
 
   return {
     name: MOBILE_FEEDBACK_INTEGRATION_NAME,
     options: widgetOptions,
     buttonOptions: buttonOptions || {},
+    screenshotButtonOptions: screenshotButtonOptions || {},
     colorScheme: colorScheme || 'system',
     themeLight: lightTheme || {},
     themeDark: darkTheme || {},
@@ -55,6 +65,15 @@ export const getFeedbackButtonOptions = (): Partial<FeedbackButtonProps> => {
   return integration.buttonOptions;
 };
 
+export const getScreenshotButtonOptions = (): Partial<ScreenshotButtonProps> => {
+  const integration = _getClientIntegration();
+  if (!integration) {
+    return {};
+  }
+
+  return integration.screenshotButtonOptions;
+};
+
 export const getColorScheme = (): 'system' | 'light' | 'dark' => {
   const integration = _getClientIntegration();
   if (!integration) {
diff --git a/packages/core/src/js/feedback/lazy.ts b/packages/core/src/js/feedback/lazy.ts
index bf60820779..c3d2b2727d 100644
--- a/packages/core/src/js/feedback/lazy.ts
+++ b/packages/core/src/js/feedback/lazy.ts
@@ -38,3 +38,16 @@ export function lazyLoadAutoInjectFeedbackButtonIntegration(): void {
     getClient()?.addIntegration({ name: AUTO_INJECT_FEEDBACK_BUTTON_INTEGRATION_NAME });
   }
 }
+
+export const AUTO_INJECT_SCREENSHOT_BUTTON_INTEGRATION_NAME = 'AutoInjectMobileScreenshotButton';
+
+/**
+ * Lazy loads the auto inject screenshot button integration if it is not already loaded.
+ */
+export function lazyLoadAutoInjectScreenshotButtonIntegration(): void {
+  const integration = getClient()?.getIntegrationByName(AUTO_INJECT_SCREENSHOT_BUTTON_INTEGRATION_NAME);
+  if (!integration) {
+    // Lazy load the integration to track usage
+    getClient()?.addIntegration({ name: AUTO_INJECT_SCREENSHOT_BUTTON_INTEGRATION_NAME });
+  }
+}
diff --git a/packages/core/src/js/wrapper.ts b/packages/core/src/js/wrapper.ts
index 598ea7c9db..eb8faf9581 100644
--- a/packages/core/src/js/wrapper.ts
+++ b/packages/core/src/js/wrapper.ts
@@ -125,6 +125,8 @@ interface SentryNativeWrapper {
   popTimeToDisplayFor(key: string): Promise<number | undefined | null>;
 
   setActiveSpanId(spanId: string): void;
+
+  encodeToBase64(data: Uint8Array): Promise<string | null>;
 }
 
 const EOL = utf8ToBytes('\n');
@@ -746,6 +748,21 @@ export const NATIVE: SentryNativeWrapper = {
     }
   },
 
+  async encodeToBase64(data: Uint8Array): Promise<string | null> {
+    if (!this.enableNative || !this._isModuleLoaded(RNSentry)) {
+      return Promise.resolve(null);
+    }
+
+    try {
+      const byteArray = Array.from(data);
+      const base64 = await RNSentry.encodeToBase64(byteArray);
+      return base64 || null;
+    } catch (error) {
+      logger.error('Error:', error);
+      return Promise.resolve(null);
+    }
+  },
+
   /**
    * Gets the event from envelopeItem and applies the level filter to the selected event.
    * @param data An envelope item containing the event.
diff --git a/packages/core/test/feedback/FeedbackWidgetManager.test.tsx b/packages/core/test/feedback/FeedbackWidgetManager.test.tsx
index 8449f0e366..e62648a2d9 100644
--- a/packages/core/test/feedback/FeedbackWidgetManager.test.tsx
+++ b/packages/core/test/feedback/FeedbackWidgetManager.test.tsx
@@ -1,7 +1,7 @@
 import { getClient, logger, setCurrentClient } from '@sentry/core';
 import { render } from '@testing-library/react-native';
 import * as React from 'react';
-import { Appearance,Text  } from 'react-native';
+import { Appearance, Text } from 'react-native';
 
 import { defaultConfiguration } from '../../src/js/feedback/defaults';
 import { FeedbackWidgetProvider, hideFeedbackButton,resetFeedbackButtonManager, resetFeedbackWidgetManager, showFeedbackButton, showFeedbackWidget } from '../../src/js/feedback/FeedbackWidgetManager';
diff --git a/packages/core/test/feedback/ScreenshotButton.test.tsx b/packages/core/test/feedback/ScreenshotButton.test.tsx
new file mode 100644
index 0000000000..9bcb29389e
--- /dev/null
+++ b/packages/core/test/feedback/ScreenshotButton.test.tsx
@@ -0,0 +1,219 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot(); // cleans up stored screenshot if any
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const defaultProps: ScreenshotButtonProps = {
+      triggerLabel: 'Take Screenshot',
+    };
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyles: ScreenshotButtonStyles = {
+      triggerButton: {
+        backgroundColor: '#ffffff',
+      },
+      triggerText: {
+        color: '#ff0000',
+      },
+    };
+    const customStyleProps = {styles: customStyles};
+    const { toJSON } = render(<ScreenshotButton {...customStyleProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('the take screenshot button is visible in the feedback widget when enabled', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+
+    const takeScreenshotButton = getByText('Take a screenshot');
+    expect(takeScreenshotButton).toBeTruthy();
+  });
+
+
+  it('the capture screenshot button is shown when tapping the Take a screenshot button in the feedback widget', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+
+    const captureButton = getByText('Take Screenshot');
+    expect(captureButton).toBeTruthy();
+  });
+
+  it('a screenshot is captured when tapping the Take Screenshot button', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+  });
+
+  it('the feedback widget ui is updated when a screenshot is captured', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).toBeNull();
+    });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
+      expect(takeScreenshotButtonAfterCapture).toBeNull();
+    });
+
+    await waitFor(() => {
+      const removeScreenshotButtonAfterCapture = queryByText('Remove screenshot');
+      expect(removeScreenshotButtonAfterCapture).toBeTruthy();
+    });
+  });
+
+  it('when the capture fails the capture button is still visible', async () => {
+    mockCaptureScreenshot.mockResolvedValue([]);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).not.toBeNull();
+    });
+  });
+});
diff --git a/packages/core/test/feedback/__snapshots__/ScreenshotButton.test.tsx.snap b/packages/core/test/feedback/__snapshots__/ScreenshotButton.test.tsx.snap
new file mode 100644
index 0000000000..2cd6455502
--- /dev/null
+++ b/packages/core/test/feedback/__snapshots__/ScreenshotButton.test.tsx.snap
@@ -0,0 +1,253 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ScreenshotButton matches the snapshot with custom styles 1`] = `
+<View
+  accessibilityLabel=""
+  accessibilityState={
+    {
+      "busy": undefined,
+      "checked": undefined,
+      "disabled": undefined,
+      "expanded": undefined,
+      "selected": undefined,
+    }
+  }
+  accessibilityValue={
+    {
+      "max": undefined,
+      "min": undefined,
+      "now": undefined,
+      "text": undefined,
+    }
+  }
+  accessible={true}
+  collapsable={false}
+  focusable={true}
+  onClick={[Function]}
+  onResponderGrant={[Function]}
+  onResponderMove={[Function]}
+  onResponderRelease={[Function]}
+  onResponderTerminate={[Function]}
+  onResponderTerminationRequest={[Function]}
+  onStartShouldSetResponder={[Function]}
+  style={
+    {
+      "alignItems": "center",
+      "backgroundColor": "#ffffff",
+      "borderColor": "rgba(41, 35, 47, 0.13)",
+      "borderRadius": 40,
+      "borderWidth": 1,
+      "bottom": 30,
+      "elevation": 5,
+      "flexDirection": "row",
+      "justifyContent": "center",
+      "opacity": 1,
+      "padding": 15,
+      "position": "absolute",
+      "right": 30,
+      "shadowColor": "rgba(41, 35, 47, 0.13)",
+      "shadowOffset": {
+        "height": 2,
+        "width": 1,
+      },
+      "shadowOpacity": 0.5,
+      "shadowRadius": 3,
+    }
+  }
+>
+  <Image
+    source={
+      {
+        "uri": "data:image/png;base64,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",
+      }
+    }
+    style={
+      {
+        "height": 24,
+        "marginEnd": 6,
+        "padding": 2,
+        "tintColor": "rgba(54, 45, 89, 1)",
+        "width": 24,
+      }
+    }
+  />
+  <Text
+    style={
+      {
+        "color": "#ff0000",
+        "fontSize": 18,
+      }
+    }
+  >
+    Take Screenshot
+  </Text>
+</View>
+`;
+
+exports[`ScreenshotButton matches the snapshot with custom texts 1`] = `
+<View
+  accessibilityLabel=""
+  accessibilityState={
+    {
+      "busy": undefined,
+      "checked": undefined,
+      "disabled": undefined,
+      "expanded": undefined,
+      "selected": undefined,
+    }
+  }
+  accessibilityValue={
+    {
+      "max": undefined,
+      "min": undefined,
+      "now": undefined,
+      "text": undefined,
+    }
+  }
+  accessible={true}
+  collapsable={false}
+  focusable={true}
+  onClick={[Function]}
+  onResponderGrant={[Function]}
+  onResponderMove={[Function]}
+  onResponderRelease={[Function]}
+  onResponderTerminate={[Function]}
+  onResponderTerminationRequest={[Function]}
+  onStartShouldSetResponder={[Function]}
+  style={
+    {
+      "alignItems": "center",
+      "backgroundColor": "#ffffff",
+      "borderColor": "rgba(41, 35, 47, 0.13)",
+      "borderRadius": 40,
+      "borderWidth": 1,
+      "bottom": 30,
+      "elevation": 5,
+      "flexDirection": "row",
+      "justifyContent": "center",
+      "opacity": 1,
+      "padding": 15,
+      "position": "absolute",
+      "right": 30,
+      "shadowColor": "rgba(41, 35, 47, 0.13)",
+      "shadowOffset": {
+        "height": 2,
+        "width": 1,
+      },
+      "shadowOpacity": 0.5,
+      "shadowRadius": 3,
+    }
+  }
+>
+  <Image
+    source={
+      {
+        "uri": "data:image/png;base64,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",
+      }
+    }
+    style={
+      {
+        "height": 24,
+        "marginEnd": 6,
+        "padding": 2,
+        "tintColor": "rgba(54, 45, 89, 1)",
+        "width": 24,
+      }
+    }
+  />
+  <Text
+    style={
+      {
+        "color": "#2b2233",
+        "fontSize": 18,
+      }
+    }
+  >
+    Take Screenshot
+  </Text>
+</View>
+`;
+
+exports[`ScreenshotButton matches the snapshot with default configuration 1`] = `
+<View
+  accessibilityLabel=""
+  accessibilityState={
+    {
+      "busy": undefined,
+      "checked": undefined,
+      "disabled": undefined,
+      "expanded": undefined,
+      "selected": undefined,
+    }
+  }
+  accessibilityValue={
+    {
+      "max": undefined,
+      "min": undefined,
+      "now": undefined,
+      "text": undefined,
+    }
+  }
+  accessible={true}
+  collapsable={false}
+  focusable={true}
+  onClick={[Function]}
+  onResponderGrant={[Function]}
+  onResponderMove={[Function]}
+  onResponderRelease={[Function]}
+  onResponderTerminate={[Function]}
+  onResponderTerminationRequest={[Function]}
+  onStartShouldSetResponder={[Function]}
+  style={
+    {
+      "alignItems": "center",
+      "backgroundColor": "#ffffff",
+      "borderColor": "rgba(41, 35, 47, 0.13)",
+      "borderRadius": 40,
+      "borderWidth": 1,
+      "bottom": 30,
+      "elevation": 5,
+      "flexDirection": "row",
+      "justifyContent": "center",
+      "opacity": 1,
+      "padding": 15,
+      "position": "absolute",
+      "right": 30,
+      "shadowColor": "rgba(41, 35, 47, 0.13)",
+      "shadowOffset": {
+        "height": 2,
+        "width": 1,
+      },
+      "shadowOpacity": 0.5,
+      "shadowRadius": 3,
+    }
+  }
+>
+  <Image
+    source={
+      {
+        "uri": "data:image/png;base64,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",
+      }
+    }
+    style={
+      {
+        "height": 24,
+        "marginEnd": 6,
+        "padding": 2,
+        "tintColor": "rgba(54, 45, 89, 1)",
+        "width": 24,
+      }
+    }
+  />
+  <Text
+    style={
+      {
+        "color": "#2b2233",
+        "fontSize": 18,
+      }
+    }
+  >
+    Take Screenshot
+  </Text>
+</View>
+`;
diff --git a/packages/core/test/mockWrapper.ts b/packages/core/test/mockWrapper.ts
index 5cc672a5b7..c26c384e26 100644
--- a/packages/core/test/mockWrapper.ts
+++ b/packages/core/test/mockWrapper.ts
@@ -62,6 +62,7 @@ const NATIVE: MockInterface<NativeType> = {
   getDataFromUri: jest.fn(),
   popTimeToDisplayFor: jest.fn(),
   setActiveSpanId: jest.fn(),
+  encodeToBase64: jest.fn(),
 };
 
 NATIVE.isNativeAvailable.mockReturnValue(true);
diff --git a/samples/expo/app/_layout.tsx b/samples/expo/app/_layout.tsx
index e6401ae96a..1daaad0f3e 100644
--- a/samples/expo/app/_layout.tsx
+++ b/samples/expo/app/_layout.tsx
@@ -59,6 +59,8 @@ Sentry.init({
       navigationIntegration,
       Sentry.reactNativeTracingIntegration(),
       Sentry.feedbackIntegration({
+        enableScreenshot: true,
+        enableTakeScreenshot: true,
         imagePicker: ImagePicker,
         buttonOptions: {
           styles: {
diff --git a/samples/react-native/src/App.tsx b/samples/react-native/src/App.tsx
index 21a913fddc..cddbe14e3a 100644
--- a/samples/react-native/src/App.tsx
+++ b/samples/react-native/src/App.tsx
@@ -115,6 +115,8 @@ Sentry.init({
       }),
       Sentry.feedbackIntegration({
         imagePicker: ImagePicker,
+        enableScreenshot: true,
+        enableTakeScreenshot: true,
         styles:{
           submitButton: {
             backgroundColor: '#6a1b9a',
@@ -132,6 +134,13 @@ Sentry.init({
             },
           },
         },
+        screenshotButtonOptions: {
+          styles: {
+            triggerButton: {
+              marginBottom: 75, // Place above the tab bar
+            },
+          },
+        },
       }),
     );
     return integrations.filter(i => i.name !== 'Dedupe');


Reviews:
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T14:54:49Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-04T08:38:08Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T11:07:42Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T11:23:07Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T11:33:22Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T15:30:47Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T15:30:49Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-08T09:27:00Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:27:52Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:31:31Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:34:51Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:35:50Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:40:33Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:49:01Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:49:48Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:49:53Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:49:57Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:52:13Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:54:58Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T12:57:41Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T13:06:21Z
user: login: krystofwoldrich
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T13:11:11Z
user: login: krystofwoldrich
body: Looks good, left one more small comment.

Thank you.
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T13:11:48Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-14T13:18:53Z
user: login: antonis
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-16T12:43:59Z

Review comments:
diff_hunk: @@ -311,6 +318,17 @@ export class FeedbackWidget extends React.Component<FeedbackWidgetProps, Feedbac
               </TouchableOpacity>
             </View>
           )}
+          {config.enableScreenshot && !this.state.attachmentUri && (
+            <TouchableOpacity style={styles.takeScreenshotButton} onPress={() => {
+              // eslint-disable-next-line @typescript-eslint/no-var-requires
+              const { hideFeedbackButton, showScreenshotButton } = require('./FeedbackWidgetManager');
path: packages/core/src/js/feedback/FeedbackWidget.tsx
user: login: antonis
body: The cyclic dependencies are properly fixed with a small refactoring in a followup PR https://github.com/getsentry/sentry-react-native/pull/4718
created_at: 2025-04-03T14:54:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,86 @@
+import * as React from 'react';
+import type { NativeEventSubscription} from 'react-native';
+import { Appearance, Image, Text, TouchableOpacity } from 'react-native';
+
+import type { Screenshot } from '../wrapper';
+import { NATIVE } from '../wrapper';
+import { defaultScreenshotButtonConfiguration } from './defaults';
+import { defaultScreenshotButtonStyles } from './FeedbackWidget.styles';
+import { getTheme } from './FeedbackWidget.theme';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles, ScreenshotButtonTextConfiguration } from './FeedbackWidget.types';
+import { screenshotIcon } from './icons';
+import { lazyLoadFeedbackIntegration } from './lazy';
+
+let capturedScreenshot: Screenshot | undefined;
+
+const takeScreenshot = async (): Promise<void> => {
+  const screenshots: Screenshot[] | null = await NATIVE.captureScreenshot();
+  if (screenshots && screenshots.length > 0) {
+    // eslint-disable-next-line @typescript-eslint/no-var-requires
+    const { hideScreenshotButton, showFeedbackWidget } = require('./FeedbackWidgetManager');
path: packages/core/src/js/feedback/ScreenshotButton.tsx
user: login: antonis
body: The cyclic dependencies are properly fixed with a small refactoring in a followup PR https://github.com/getsentry/sentry-react-native/pull/4718
created_at: 2025-04-04T08:38:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,14 +3,15 @@ import * as React from 'react';
 import type { NativeEventSubscription, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
 import { Animated, Appearance, Dimensions, Easing, Modal, PanResponder, Platform, ScrollView, View } from 'react-native';
 
-import { notWeb } from '../utils/environment';
+import { isWeb,notWeb  } from '../utils/environment';
 import { FeedbackButton } from './FeedbackButton';
 import { FeedbackWidget } from './FeedbackWidget';
 import { modalSheetContainer, modalWrapper, topSpacer } from './FeedbackWidget.styles';
 import { getTheme } from './FeedbackWidget.theme';
 import type { FeedbackWidgetStyles } from './FeedbackWidget.types';
-import { getFeedbackButtonOptions, getFeedbackOptions } from './integration';
-import { lazyLoadAutoInjectFeedbackButtonIntegration,lazyLoadAutoInjectFeedbackIntegration } from './lazy';
+import { getFeedbackButtonOptions, getFeedbackOptions, getScreenshotkButtonOptions } from './integration';
path: packages/core/src/js/feedback/FeedbackWidgetManager.tsx
user: login: krystofwoldrich
body: Just a typo `getScreenshotkButtonOptions` -> `getScreenshotButtonOptions`
created_at: 2025-04-07T11:07:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -89,6 +89,12 @@ export { Mask, Unmask } from './replay/CustomMask';
 
 export { FeedbackButton } from './feedback/FeedbackButton';
 export { FeedbackWidget } from './feedback/FeedbackWidget';
-export { showFeedbackWidget, showFeedbackButton, hideFeedbackButton } from './feedback/FeedbackWidgetManager';
+export {
+  showFeedbackWidget,
+  showFeedbackButton,
+  hideFeedbackButton,
+  showScreenshotButton,
+  hideScreenshotButton,
path: packages/core/src/js/index.ts
user: login: krystofwoldrich
body: I think for simplicity we could leave this API out and the taking of the screenshot would be only part of the auto injected widget.
created_at: 2025-04-07T11:23:06Z
author_association: CONTRIBUTOR
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: krystofwoldrich
body: Let's also add more complex tests, representing the user flow, widget opened, take a screenshot, press take screenshot button, show widget, button hidden.

Like the other tests in FeedbackWidgetManager.test.tsx.
created_at: 2025-04-07T11:33:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -89,6 +89,12 @@ export { Mask, Unmask } from './replay/CustomMask';
 
 export { FeedbackButton } from './feedback/FeedbackButton';
 export { FeedbackWidget } from './feedback/FeedbackWidget';
-export { showFeedbackWidget, showFeedbackButton, hideFeedbackButton } from './feedback/FeedbackWidgetManager';
+export {
+  showFeedbackWidget,
+  showFeedbackButton,
+  hideFeedbackButton,
+  showScreenshotButton,
+  hideScreenshotButton,
path: packages/core/src/js/index.ts
user: login: antonis
body: Makes sense 👍 
Updated with 1fdf12558fad0d0aa4f4c11749a77cf86af87f4d
created_at: 2025-04-07T15:30:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -3,14 +3,15 @@ import * as React from 'react';
 import type { NativeEventSubscription, NativeScrollEvent, NativeSyntheticEvent} from 'react-native';
 import { Animated, Appearance, Dimensions, Easing, Modal, PanResponder, Platform, ScrollView, View } from 'react-native';
 
-import { notWeb } from '../utils/environment';
+import { isWeb,notWeb  } from '../utils/environment';
 import { FeedbackButton } from './FeedbackButton';
 import { FeedbackWidget } from './FeedbackWidget';
 import { modalSheetContainer, modalWrapper, topSpacer } from './FeedbackWidget.styles';
 import { getTheme } from './FeedbackWidget.theme';
 import type { FeedbackWidgetStyles } from './FeedbackWidget.types';
-import { getFeedbackButtonOptions, getFeedbackOptions } from './integration';
-import { lazyLoadAutoInjectFeedbackButtonIntegration,lazyLoadAutoInjectFeedbackIntegration } from './lazy';
+import { getFeedbackButtonOptions, getFeedbackOptions, getScreenshotkButtonOptions } from './integration';
path: packages/core/src/js/feedback/FeedbackWidgetManager.tsx
user: login: antonis
body: Good catch 🙇 
Updated with 7af42d3cadc0d9604c05b1f67e0fc72ece73533b
created_at: 2025-04-07T15:30:49Z
author_association: CONTRIBUTOR
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: Good idea @krystofwoldrich 👍 
I've added more cases in [`ScreenshotButton.test.tsx`](https://github.com/getsentry/sentry-react-native/pull/4714/files#diff-bdeb2db909f1e3e22c2b4955c55de61c4e8e7ffe0ed6f275d11769ae15b341cd)

created_at: 2025-04-08T09:27:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,20 +8,23 @@ import { defaultScreenshotButtonConfiguration } from './defaults';
 import { defaultScreenshotButtonStyles } from './FeedbackWidget.styles';
 import { getTheme } from './FeedbackWidget.theme';
 import type { ScreenshotButtonProps, ScreenshotButtonStyles, ScreenshotButtonTextConfiguration } from './FeedbackWidget.types';
+import { hideScreenshotButton, showFeedbackWidget, showScreenshotButton } from './FeedbackWidgetManager';
path: packages/core/src/js/feedback/ScreenshotButton.tsx
user: login: antonis
body: The [cyclic dep failure](https://github.com/getsentry/sentry-react-native/actions/runs/14446067789/job/40506993998?pr=4714) is fixed in https://github.com/getsentry/sentry-react-native/pull/4718
created_at: 2025-04-14T12:27:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: krystofwoldrich
body: ````suggestion
    getCapturedScreenshot(); // cleans up stored screenshot if any
```` 
created_at: 2025-04-14T12:31:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: krystofwoldrich
body: Since the props object is not used anywhere else, let's define the custom test inside of the test.
created_at: 2025-04-14T12:34:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: krystofwoldrich
body: same as with the prev comment, let's define the style inside of the test
created_at: 2025-04-14T12:35:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
+    const { toJSON } = render(<ScreenshotButton {...customStyleProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('the take screenshot button is visible in the feedback widget when enabled', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+
+    const takeScreenshotButton = getByText('Take a screenshot');
+    expect(takeScreenshotButton).toBeTruthy();
+  });
+
+
+  it('the capture screenshot button is shown when tapping the Take a screenshot button in the feedback widget', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+
+    const captureButton = getByText('Take Screenshot');
+    expect(captureButton).toBeTruthy();
+  });
+
+  it('a screenshot is captured when tapping the Take Screenshot button', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+  });
+
+  it('the feedback widget ui is updated when a screenshot is captured', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).toBeNull();
+    });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: krystofwoldrich
body: `Take a screenshot` not rendered could also be because the widget has not rendered after taking the screenshot. Would it make sense to check for the `Remove screenshot` button? 

created_at: 2025-04-14T12:40:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
+    const { toJSON } = render(<ScreenshotButton {...customStyleProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('the take screenshot button is visible in the feedback widget when enabled', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+
+    const takeScreenshotButton = getByText('Take a screenshot');
+    expect(takeScreenshotButton).toBeTruthy();
+  });
+
+
+  it('the capture screenshot button is shown when tapping the Take a screenshot button in the feedback widget', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+
+    const captureButton = getByText('Take Screenshot');
+    expect(captureButton).toBeTruthy();
+  });
+
+  it('a screenshot is captured when tapping the Take Screenshot button', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+  });
+
+  it('the feedback widget ui is updated when a screenshot is captured', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).toBeNull();
+    });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
+      expect(takeScreenshotButtonAfterCapture).toBeNull();
+    });
+  });
+
+  it('when the capture fails the capture button is still visible', async () => {
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: krystofwoldrich
body: Possibly for a follow-up PR, this sounds like the users would get stuck on the screen with the `Take Screenshot` button if the screenshots are not working.

I don't know how likely that is, but maybe we should show alert and return to the widget. What do you think, @antonis?
created_at: 2025-04-14T12:49:01Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: Updated with 422b6d27bc8162d0623da25cb6a35e159d7bb5ca 🙇 
created_at: 2025-04-14T12:49:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: Good point 👍 Updated with 262be2adb4d52277beed545f0e3997673f810b04
created_at: 2025-04-14T12:49:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: Good idea Krystof 👍 Added with 48638b8a12d0b2edc1179466e05040b8b39b2032
created_at: 2025-04-14T12:49:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
+    const { toJSON } = render(<ScreenshotButton {...customStyleProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('the take screenshot button is visible in the feedback widget when enabled', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+
+    const takeScreenshotButton = getByText('Take a screenshot');
+    expect(takeScreenshotButton).toBeTruthy();
+  });
+
+
+  it('the capture screenshot button is shown when tapping the Take a screenshot button in the feedback widget', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+
+    const captureButton = getByText('Take Screenshot');
+    expect(captureButton).toBeTruthy();
+  });
+
+  it('a screenshot is captured when tapping the Take Screenshot button', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+  });
+
+  it('the feedback widget ui is updated when a screenshot is captured', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).toBeNull();
+    });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: Good point Krystof 👍 Added with 8876d89e50d814270cab338d3feb96e1355b4082
For some reason this was flaky 885399c5300003f787327dd9c488b399dccf9f8d in my original tests but it seems to work now :) 🤞 

created_at: 2025-04-14T12:52:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
+    const { toJSON } = render(<ScreenshotButton {...customStyleProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('the take screenshot button is visible in the feedback widget when enabled', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+
+    const takeScreenshotButton = getByText('Take a screenshot');
+    expect(takeScreenshotButton).toBeTruthy();
+  });
+
+
+  it('the capture screenshot button is shown when tapping the Take a screenshot button in the feedback widget', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+
+    const captureButton = getByText('Take Screenshot');
+    expect(captureButton).toBeTruthy();
+  });
+
+  it('a screenshot is captured when tapping the Take Screenshot button', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+  });
+
+  it('the feedback widget ui is updated when a screenshot is captured', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).toBeNull();
+    });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
+      expect(takeScreenshotButtonAfterCapture).toBeNull();
+    });
+  });
+
+  it('when the capture fails the capture button is still visible', async () => {
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: Yes, that's the current behaviour. I haven't managed to reproduce this but I think it's a good idea to follow up on this and show again the widget with an error
created_at: 2025-04-14T12:54:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
+    const { toJSON } = render(<ScreenshotButton {...customStyleProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('the take screenshot button is visible in the feedback widget when enabled', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+
+    const takeScreenshotButton = getByText('Take a screenshot');
+    expect(takeScreenshotButton).toBeTruthy();
+  });
+
+
+  it('the capture screenshot button is shown when tapping the Take a screenshot button in the feedback widget', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+
+    const captureButton = getByText('Take Screenshot');
+    expect(captureButton).toBeTruthy();
+  });
+
+  it('a screenshot is captured when tapping the Take Screenshot button', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+  });
+
+  it('the feedback widget ui is updated when a screenshot is captured', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).toBeNull();
+    });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
+      expect(takeScreenshotButtonAfterCapture).toBeNull();
+    });
+  });
+
+  it('when the capture fails the capture button is still visible', async () => {
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: > I don't know how likely that is, but maybe we should show alert and return to the widget. What do you think, @antonis?

I agree 👍 I'll follow up with a separate PR.
created_at: 2025-04-14T12:57:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
+    const { toJSON } = render(<ScreenshotButton {...customStyleProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('the take screenshot button is visible in the feedback widget when enabled', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+
+    const takeScreenshotButton = getByText('Take a screenshot');
+    expect(takeScreenshotButton).toBeTruthy();
+  });
+
+
+  it('the capture screenshot button is shown when tapping the Take a screenshot button in the feedback widget', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+
+    const captureButton = getByText('Take Screenshot');
+    expect(captureButton).toBeTruthy();
+  });
+
+  it('a screenshot is captured when tapping the Take Screenshot button', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+  });
+
+  it('the feedback widget ui is updated when a screenshot is captured', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).toBeNull();
+    });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: krystofwoldrich
body: Thanks for the context; I didn't know that. 
created_at: 2025-04-14T13:06:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -180,6 +180,11 @@ describe('ScreenshotButton', () => {
       const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
       expect(takeScreenshotButtonAfterCapture).toBeNull();
     });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Remove screenshot');
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: krystofwoldrich
body: L: Just fixed the name and double negation not null.

````suggestion
      const removeScreenshotButtonAfterCapture = queryByText('Remove screenshot');
      expect(removeScreenshotButtonAfterCapture).toBeTruthy();
```` 	
created_at: 2025-04-14T13:11:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -180,6 +180,11 @@ describe('ScreenshotButton', () => {
       const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
       expect(takeScreenshotButtonAfterCapture).toBeNull();
     });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Remove screenshot');
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: Good catch Krystof 🙇 
Updated with 59597a4c99fb50675f62eb7c5f7c3ccd9bf0a169
created_at: 2025-04-14T13:18:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,216 @@
+import { getClient, setCurrentClient } from '@sentry/core';
+import { fireEvent, render, waitFor } from '@testing-library/react-native';
+import * as React from 'react';
+import { Text } from 'react-native';
+
+import { FeedbackWidget } from '../../src/js/feedback/FeedbackWidget';
+import type { ScreenshotButtonProps, ScreenshotButtonStyles } from '../../src/js/feedback/FeedbackWidget.types';
+import { FeedbackWidgetProvider, resetFeedbackButtonManager, resetFeedbackWidgetManager, resetScreenshotButtonManager, showFeedbackButton } from '../../src/js/feedback/FeedbackWidgetManager';
+import { feedbackIntegration } from '../../src/js/feedback/integration';
+import { getCapturedScreenshot, ScreenshotButton } from '../../src/js/feedback/ScreenshotButton';
+import type { Screenshot } from '../../src/js/wrapper';
+import { NATIVE  } from '../../src/js/wrapper';
+import { getDefaultTestClientOptions, TestClient } from '../mocks/client';
+
+jest.mock('../../src/js/wrapper', () => ({
+  NATIVE: {
+    captureScreenshot: jest.fn(),
+    encodeToBase64: jest.fn(),
+  },
+}));
+
+const mockScreenshot: Screenshot = {
+  filename: 'test-screenshot.png',
+  contentType: 'image/png',
+  data: new Uint8Array([1, 2, 3]),
+};
+
+const mockBase64Image = 'mockBase64ImageString';
+
+const mockCaptureScreenshot = NATIVE.captureScreenshot as jest.Mock;
+const mockEncodeToBase64 = NATIVE.encodeToBase64 as jest.Mock;
+
+const defaultProps: ScreenshotButtonProps = {
+  triggerLabel: 'Take Screenshot',
+};
+
+export const customStyles: ScreenshotButtonStyles = {
+  triggerButton: {
+    backgroundColor: '#ffffff',
+  },
+  triggerText: {
+    color: '#ff0000',
+  },
+};
+
+describe('ScreenshotButton', () => {
+  beforeEach(() => {
+    jest.clearAllMocks();
+    FeedbackWidget.reset();
+    getCapturedScreenshot();
+    resetFeedbackWidgetManager();
+    resetFeedbackButtonManager();
+    resetScreenshotButtonManager();
+    const client = new TestClient(getDefaultTestClientOptions());
+    setCurrentClient(client);
+    client.init();
+  });
+
+  it('matches the snapshot with default configuration', () => {
+    const { toJSON } = render(<ScreenshotButton/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom texts', () => {
+    const { toJSON } = render(<ScreenshotButton {...defaultProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('matches the snapshot with custom styles', () => {
+    const customStyleProps = {styles: customStyles};
+    const { toJSON } = render(<ScreenshotButton {...customStyleProps}/>);
+    expect(toJSON()).toMatchSnapshot();
+  });
+
+  it('the take screenshot button is visible in the feedback widget when enabled', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+
+    const takeScreenshotButton = getByText('Take a screenshot');
+    expect(takeScreenshotButton).toBeTruthy();
+  });
+
+
+  it('the capture screenshot button is shown when tapping the Take a screenshot button in the feedback widget', async () => {
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+
+    const captureButton = getByText('Take Screenshot');
+    expect(captureButton).toBeTruthy();
+  });
+
+  it('a screenshot is captured when tapping the Take Screenshot button', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+  });
+
+  it('the feedback widget ui is updated when a screenshot is captured', async () => {
+    mockCaptureScreenshot.mockResolvedValue([mockScreenshot]);
+    mockEncodeToBase64.mockResolvedValue(mockBase64Image);
+
+    const { getByText, queryByText } = render(
+      <FeedbackWidgetProvider>
+        <Text>App Components</Text>
+      </FeedbackWidgetProvider>
+    );
+
+    const integration = feedbackIntegration({
+      enableTakeScreenshot: true,
+    });
+    getClient()?.addIntegration(integration);
+
+    showFeedbackButton();
+
+    fireEvent.press(getByText('Report a Bug'));
+    fireEvent.press(getByText('Take a screenshot'));
+    fireEvent.press(getByText('Take Screenshot'));
+
+    await waitFor(() => {
+      expect(mockCaptureScreenshot).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      expect(mockEncodeToBase64).toHaveBeenCalled();
+    });
+
+    await waitFor(() => {
+      const captureButton = queryByText('Take Screenshot');
+      expect(captureButton).toBeNull();
+    });
+
+    await waitFor(() => {
+      const takeScreenshotButtonAfterCapture = queryByText('Take a screenshot');
+      expect(takeScreenshotButtonAfterCapture).toBeNull();
+    });
+  });
+
+  it('when the capture fails the capture button is still visible', async () => {
path: packages/core/test/feedback/ScreenshotButton.test.tsx
user: login: antonis
body: Followed up in https://github.com/getsentry/sentry-react-native/pull/4757
created_at: 2025-04-16T12:43:59Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-31T16:28:41Z
body: 
<!--
  0 failure: 
  0 warning: 
  1 messages
  
  DangerID: danger-id-Danger;
-->



<table>
  <thead>
    <tr>
      <th width="50"></th>
      <th width="100%" data-danger-table="true">Messages</th>
    </tr>
  </thead>
  <tbody><tr>
      <td>:book:</td>
      <td>Do not forget to update <a href="https://github.com/getsentry/sentry-docs">Sentry-docs</a> with your feature once the pull request gets approved.</td>
    </tr>
  </tbody>
</table>


<p align="right">
  Generated by :no_entry_sign: <a href="https://danger.systems/js">dangerJS</a> against 59597a4c99fb50675f62eb7c5f7c3ccd9bf0a169
</p>

author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-31T17:51:37Z
body: ## Android (legacy) Performance metrics :rocket:
<table>
  <tr>
    <th>&nbsp;</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr>
  <tr>
    <th align="left">Startup time</th>
    <td align="right">468.79 ms</td>
    <td align="right">473.29 ms</td>
    <td align="right"><strong>4.50 ms</strong></td>
  </tr>
  <tr>
    <th align="left">Size</th>
    <td align="right">17.75 MiB</td>
    <td align="right">20.15 MiB</td>
    <td align="right"><strong>2.40 MiB</strong></td>
  </tr>
</table>
<details><summary><h3>Baseline results on branch: feedback-ui-2</h3></summary>
<h3>Startup times</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">6e4d2e149ae7957f51a908b9a03194401c47cdca</th>
  <td align="right">435.80 ms</td>
  <td align="right">432.63 ms</td>
  <td align="right"><strong>-3.17 ms</strong></td>
</tr></table>
<h3>App size</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">6e4d2e149ae7957f51a908b9a03194401c47cdca</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.13 MiB</td>
  <td align="right"><strong>2.39 MiB</strong></td>
</tr></table>
</details>
<details><summary><h3>Previous results on branch: antonis/screenshot-button</h3></summary>
<h3>Startup times</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">87a3299d3c5a64dd5ef5bacf71c1fcd6ddf59be4</th>
  <td align="right">434.60 ms</td>
  <td align="right">439.06 ms</td>
  <td align="right"><strong>4.46 ms</strong></td>
</tr><tr>
  <th align="left">ec3bff494e349214b579162d162abc2e364772d9</th>
  <td align="right">460.68 ms</td>
  <td align="right">460.38 ms</td>
  <td align="right"><strong>-0.30 ms</strong></td>
</tr><tr>
  <th align="left">7645d55dc2e32e97d5a878116a6b8dfc51ae3fbb</th>
  <td align="right">448.29 ms</td>
  <td align="right">503.00 ms</td>
  <td align="right"><strong>54.71 ms</strong></td>
</tr><tr>
  <th align="left">ebf24725a3a8448dfde3d228f450b4b74c44f79a</th>
  <td align="right">679.39 ms</td>
  <td align="right">718.56 ms</td>
  <td align="right"><strong>39.17 ms</strong></td>
</tr><tr>
  <th align="left">8939c3fc9b16bf12a63d59053b23a2b07050e658</th>
  <td align="right">461.60 ms</td>
  <td align="right">443.40 ms</td>
  <td align="right"><strong>-18.20 ms</strong></td>
</tr><tr>
  <th align="left">d95e4d62fb51217f1e678547a0a2bb731ef029c8</th>
  <td align="right">474.00 ms</td>
  <td align="right">515.02 ms</td>
  <td align="right"><strong>41.02 ms</strong></td>
</tr><tr>
  <th align="left">a88fdb9c8fae3d579ebce5f9c8448089042df4b5</th>
  <td align="right">433.38 ms</td>
  <td align="right">418.67 ms</td>
  <td align="right"><strong>-14.71 ms</strong></td>
</tr><tr>
  <th align="left">9b3dbac3c099aac00d8ee424c2532e5c7efef51d</th>
  <td align="right">461.49 ms</td>
  <td align="right">476.39 ms</td>
  <td align="right"><strong>14.90 ms</strong></td>
</tr><tr>
  <th align="left">46de2b50fed68afb904de0e265c7daa1ebcf5926</th>
  <td align="right">446.49 ms</td>
  <td align="right">437.78 ms</td>
  <td align="right"><strong>-8.71 ms</strong></td>
</tr><tr>
  <th align="left">0814326da81627d28511b5e815a0bd97e3495fdd</th>
  <td align="right">418.53 ms</td>
  <td align="right">430.60 ms</td>
  <td align="right"><strong>12.07 ms</strong></td>
</tr></table>
<h3>App size</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">87a3299d3c5a64dd5ef5bacf71c1fcd6ddf59be4</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr><tr>
  <th align="left">ec3bff494e349214b579162d162abc2e364772d9</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr><tr>
  <th align="left">7645d55dc2e32e97d5a878116a6b8dfc51ae3fbb</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr><tr>
  <th align="left">ebf24725a3a8448dfde3d228f450b4b74c44f79a</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr><tr>
  <th align="left">8939c3fc9b16bf12a63d59053b23a2b07050e658</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr><tr>
  <th align="left">d95e4d62fb51217f1e678547a0a2bb731ef029c8</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.13 MiB</td>
  <td align="right"><strong>2.39 MiB</strong></td>
</tr><tr>
  <th align="left">a88fdb9c8fae3d579ebce5f9c8448089042df4b5</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr><tr>
  <th align="left">9b3dbac3c099aac00d8ee424c2532e5c7efef51d</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr><tr>
  <th align="left">46de2b50fed68afb904de0e265c7daa1ebcf5926</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr><tr>
  <th align="left">0814326da81627d28511b5e815a0bd97e3495fdd</th>
  <td align="right">17.75 MiB</td>
  <td align="right">20.15 MiB</td>
  <td align="right"><strong>2.40 MiB</strong></td>
</tr></table>
</details>

author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-31T17:52:56Z
body: ## Android (new) Performance metrics :rocket:
<table>
  <tr>
    <th>&nbsp;</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr>
  <tr>
    <th align="left">Startup time</th>
    <td align="right">382.81 ms</td>
    <td align="right">384.61 ms</td>
    <td align="right"><strong>1.80 ms</strong></td>
  </tr>
  <tr>
    <th align="left">Size</th>
    <td align="right">7.15 MiB</td>
    <td align="right">8.42 MiB</td>
    <td align="right"><strong>1.26 MiB</strong></td>
  </tr>
</table>
<details><summary><h3>Baseline results on branch: feedback-ui-2</h3></summary>
<h3>Startup times</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">6e4d2e149ae7957f51a908b9a03194401c47cdca+dirty</th>
  <td align="right">394.19 ms</td>
  <td align="right">378.08 ms</td>
  <td align="right"><strong>-16.11 ms</strong></td>
</tr></table>
<h3>App size</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">6e4d2e149ae7957f51a908b9a03194401c47cdca+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.40 MiB</td>
  <td align="right"><strong>1.25 MiB</strong></td>
</tr></table>
</details>
<details><summary><h3>Previous results on branch: antonis/screenshot-button</h3></summary>
<h3>Startup times</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">87a3299d3c5a64dd5ef5bacf71c1fcd6ddf59be4+dirty</th>
  <td align="right">666.74 ms</td>
  <td align="right">694.30 ms</td>
  <td align="right"><strong>27.56 ms</strong></td>
</tr><tr>
  <th align="left">ec3bff494e349214b579162d162abc2e364772d9+dirty</th>
  <td align="right">395.57 ms</td>
  <td align="right">396.39 ms</td>
  <td align="right"><strong>0.82 ms</strong></td>
</tr><tr>
  <th align="left">d95e4d62fb51217f1e678547a0a2bb731ef029c8+dirty</th>
  <td align="right">448.59 ms</td>
  <td align="right">479.29 ms</td>
  <td align="right"><strong>30.70 ms</strong></td>
</tr><tr>
  <th align="left">46de2b50fed68afb904de0e265c7daa1ebcf5926+dirty</th>
  <td align="right">415.53 ms</td>
  <td align="right">431.52 ms</td>
  <td align="right"><strong>15.99 ms</strong></td>
</tr><tr>
  <th align="left">a88fdb9c8fae3d579ebce5f9c8448089042df4b5+dirty</th>
  <td align="right">373.65 ms</td>
  <td align="right">367.40 ms</td>
  <td align="right"><strong>-6.25 ms</strong></td>
</tr><tr>
  <th align="left">71a26faea11029aaafe94d85e648bf3d6b97ece2+dirty</th>
  <td align="right">400.62 ms</td>
  <td align="right">387.43 ms</td>
  <td align="right"><strong>-13.20 ms</strong></td>
</tr><tr>
  <th align="left">8939c3fc9b16bf12a63d59053b23a2b07050e658+dirty</th>
  <td align="right">417.02 ms</td>
  <td align="right">421.35 ms</td>
  <td align="right"><strong>4.33 ms</strong></td>
</tr><tr>
  <th align="left">ebf24725a3a8448dfde3d228f450b4b74c44f79a+dirty</th>
  <td align="right">416.04 ms</td>
  <td align="right">436.48 ms</td>
  <td align="right"><strong>20.44 ms</strong></td>
</tr><tr>
  <th align="left">0814326da81627d28511b5e815a0bd97e3495fdd+dirty</th>
  <td align="right">410.41 ms</td>
  <td align="right">451.87 ms</td>
  <td align="right"><strong>41.46 ms</strong></td>
</tr><tr>
  <th align="left">9b3dbac3c099aac00d8ee424c2532e5c7efef51d+dirty</th>
  <td align="right">377.63 ms</td>
  <td align="right">378.10 ms</td>
  <td align="right"><strong>0.47 ms</strong></td>
</tr></table>
<h3>App size</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">87a3299d3c5a64dd5ef5bacf71c1fcd6ddf59be4+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr><tr>
  <th align="left">ec3bff494e349214b579162d162abc2e364772d9+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr><tr>
  <th align="left">d95e4d62fb51217f1e678547a0a2bb731ef029c8+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.40 MiB</td>
  <td align="right"><strong>1.25 MiB</strong></td>
</tr><tr>
  <th align="left">46de2b50fed68afb904de0e265c7daa1ebcf5926+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr><tr>
  <th align="left">a88fdb9c8fae3d579ebce5f9c8448089042df4b5+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr><tr>
  <th align="left">71a26faea11029aaafe94d85e648bf3d6b97ece2+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr><tr>
  <th align="left">8939c3fc9b16bf12a63d59053b23a2b07050e658+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr><tr>
  <th align="left">ebf24725a3a8448dfde3d228f450b4b74c44f79a+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr><tr>
  <th align="left">0814326da81627d28511b5e815a0bd97e3495fdd+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr><tr>
  <th align="left">9b3dbac3c099aac00d8ee424c2532e5c7efef51d+dirty</th>
  <td align="right">7.15 MiB</td>
  <td align="right">8.41 MiB</td>
  <td align="right"><strong>1.26 MiB</strong></td>
</tr></table>
</details>

author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-31T17:57:32Z
body: ## iOS (legacy) Performance metrics :rocket:
<table>
  <tr>
    <th>&nbsp;</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr>
  <tr>
    <th align="left">Startup time</th>
    <td align="right">1212.21 ms</td>
    <td align="right">1218.24 ms</td>
    <td align="right"><strong>6.03 ms</strong></td>
  </tr>
  <tr>
    <th align="left">Size</th>
    <td align="right">2.63 MiB</td>
    <td align="right">3.78 MiB</td>
    <td align="right"><strong>1.15 MiB</strong></td>
  </tr>
</table>
<details><summary><h3>Baseline results on branch: feedback-ui-2</h3></summary>
<h3>Startup times</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">6e4d2e149ae7957f51a908b9a03194401c47cdca+dirty</th>
  <td align="right">1231.82 ms</td>
  <td align="right">1240.18 ms</td>
  <td align="right"><strong>8.36 ms</strong></td>
</tr></table>
<h3>App size</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">6e4d2e149ae7957f51a908b9a03194401c47cdca+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.77 MiB</td>
  <td align="right"><strong>1.14 MiB</strong></td>
</tr></table>
</details>
<details><summary><h3>Previous results on branch: antonis/screenshot-button</h3></summary>
<h3>Startup times</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">9b3dbac3c099aac00d8ee424c2532e5c7efef51d+dirty</th>
  <td align="right">1238.98 ms</td>
  <td align="right">1228.59 ms</td>
  <td align="right"><strong>-10.39 ms</strong></td>
</tr><tr>
  <th align="left">87a3299d3c5a64dd5ef5bacf71c1fcd6ddf59be4+dirty</th>
  <td align="right">1223.17 ms</td>
  <td align="right">1223.15 ms</td>
  <td align="right"><strong>-0.02 ms</strong></td>
</tr><tr>
  <th align="left">7645d55dc2e32e97d5a878116a6b8dfc51ae3fbb+dirty</th>
  <td align="right">1232.06 ms</td>
  <td align="right">1238.18 ms</td>
  <td align="right"><strong>6.12 ms</strong></td>
</tr><tr>
  <th align="left">ebf24725a3a8448dfde3d228f450b4b74c44f79a+dirty</th>
  <td align="right">1239.50 ms</td>
  <td align="right">1231.61 ms</td>
  <td align="right"><strong>-7.89 ms</strong></td>
</tr><tr>
  <th align="left">a88fdb9c8fae3d579ebce5f9c8448089042df4b5+dirty</th>
  <td align="right">1226.08 ms</td>
  <td align="right">1232.94 ms</td>
  <td align="right"><strong>6.86 ms</strong></td>
</tr><tr>
  <th align="left">ec3bff494e349214b579162d162abc2e364772d9+dirty</th>
  <td align="right">1223.41 ms</td>
  <td align="right">1232.78 ms</td>
  <td align="right"><strong>9.37 ms</strong></td>
</tr><tr>
  <th align="left">71a26faea11029aaafe94d85e648bf3d6b97ece2+dirty</th>
  <td align="right">1225.88 ms</td>
  <td align="right">1237.06 ms</td>
  <td align="right"><strong>11.18 ms</strong></td>
</tr><tr>
  <th align="left">8939c3fc9b16bf12a63d59053b23a2b07050e658+dirty</th>
  <td align="right">1219.04 ms</td>
  <td align="right">1225.73 ms</td>
  <td align="right"><strong>6.69 ms</strong></td>
</tr><tr>
  <th align="left">d95e4d62fb51217f1e678547a0a2bb731ef029c8+dirty</th>
  <td align="right">1219.45 ms</td>
  <td align="right">1219.87 ms</td>
  <td align="right"><strong>0.42 ms</strong></td>
</tr><tr>
  <th align="left">0814326da81627d28511b5e815a0bd97e3495fdd+dirty</th>
  <td align="right">1220.15 ms</td>
  <td align="right">1210.24 ms</td>
  <td align="right"><strong>-9.90 ms</strong></td>
</tr></table>
<h3>App size</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">9b3dbac3c099aac00d8ee424c2532e5c7efef51d+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">87a3299d3c5a64dd5ef5bacf71c1fcd6ddf59be4+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">7645d55dc2e32e97d5a878116a6b8dfc51ae3fbb+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">ebf24725a3a8448dfde3d228f450b4b74c44f79a+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">a88fdb9c8fae3d579ebce5f9c8448089042df4b5+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">ec3bff494e349214b579162d162abc2e364772d9+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">71a26faea11029aaafe94d85e648bf3d6b97ece2+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">8939c3fc9b16bf12a63d59053b23a2b07050e658+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">d95e4d62fb51217f1e678547a0a2bb731ef029c8+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.77 MiB</td>
  <td align="right"><strong>1.14 MiB</strong></td>
</tr><tr>
  <th align="left">0814326da81627d28511b5e815a0bd97e3495fdd+dirty</th>
  <td align="right">2.63 MiB</td>
  <td align="right">3.78 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr></table>
</details>

author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-03-31T18:10:10Z
body: ## iOS (new) Performance metrics :rocket:
<table>
  <tr>
    <th>&nbsp;</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr>
  <tr>
    <th align="left">Startup time</th>
    <td align="right">1227.57 ms</td>
    <td align="right">1223.59 ms</td>
    <td align="right"><strong>-3.98 ms</strong></td>
  </tr>
  <tr>
    <th align="left">Size</th>
    <td align="right">3.19 MiB</td>
    <td align="right">4.35 MiB</td>
    <td align="right"><strong>1.16 MiB</strong></td>
  </tr>
</table>
<details><summary><h3>Baseline results on branch: feedback-ui-2</h3></summary>
<h3>Startup times</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">6e4d2e149ae7957f51a908b9a03194401c47cdca+dirty</th>
  <td align="right">1226.76 ms</td>
  <td align="right">1233.13 ms</td>
  <td align="right"><strong>6.37 ms</strong></td>
</tr></table>
<h3>App size</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">6e4d2e149ae7957f51a908b9a03194401c47cdca+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.33 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr></table>
</details>
<details><summary><h3>Previous results on branch: antonis/screenshot-button</h3></summary>
<h3>Startup times</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">9b3dbac3c099aac00d8ee424c2532e5c7efef51d+dirty</th>
  <td align="right">1241.47 ms</td>
  <td align="right">1243.43 ms</td>
  <td align="right"><strong>1.96 ms</strong></td>
</tr><tr>
  <th align="left">87a3299d3c5a64dd5ef5bacf71c1fcd6ddf59be4+dirty</th>
  <td align="right">1219.06 ms</td>
  <td align="right">1221.71 ms</td>
  <td align="right"><strong>2.65 ms</strong></td>
</tr><tr>
  <th align="left">7645d55dc2e32e97d5a878116a6b8dfc51ae3fbb+dirty</th>
  <td align="right">1233.55 ms</td>
  <td align="right">1229.20 ms</td>
  <td align="right"><strong>-4.36 ms</strong></td>
</tr><tr>
  <th align="left">ebf24725a3a8448dfde3d228f450b4b74c44f79a+dirty</th>
  <td align="right">1231.73 ms</td>
  <td align="right">1224.76 ms</td>
  <td align="right"><strong>-6.97 ms</strong></td>
</tr><tr>
  <th align="left">a88fdb9c8fae3d579ebce5f9c8448089042df4b5+dirty</th>
  <td align="right">1221.57 ms</td>
  <td align="right">1226.20 ms</td>
  <td align="right"><strong>4.63 ms</strong></td>
</tr><tr>
  <th align="left">ec3bff494e349214b579162d162abc2e364772d9+dirty</th>
  <td align="right">1219.61 ms</td>
  <td align="right">1222.82 ms</td>
  <td align="right"><strong>3.20 ms</strong></td>
</tr><tr>
  <th align="left">71a26faea11029aaafe94d85e648bf3d6b97ece2+dirty</th>
  <td align="right">1212.48 ms</td>
  <td align="right">1215.50 ms</td>
  <td align="right"><strong>3.02 ms</strong></td>
</tr><tr>
  <th align="left">8939c3fc9b16bf12a63d59053b23a2b07050e658+dirty</th>
  <td align="right">1222.23 ms</td>
  <td align="right">1237.10 ms</td>
  <td align="right"><strong>14.87 ms</strong></td>
</tr><tr>
  <th align="left">d95e4d62fb51217f1e678547a0a2bb731ef029c8+dirty</th>
  <td align="right">1227.37 ms</td>
  <td align="right">1219.30 ms</td>
  <td align="right"><strong>-8.07 ms</strong></td>
</tr><tr>
  <th align="left">0814326da81627d28511b5e815a0bd97e3495fdd+dirty</th>
  <td align="right">1228.31 ms</td>
  <td align="right">1230.33 ms</td>
  <td align="right"><strong>2.02 ms</strong></td>
</tr></table>
<h3>App size</h3>
<table>
  <tr>
    <th>Revision</th>
    <th align="right">Plain</th>
    <th align="right">With Sentry</th>
    <th align="right">Diff</th>
  </tr><tr>
  <th align="left">9b3dbac3c099aac00d8ee424c2532e5c7efef51d+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr><tr>
  <th align="left">87a3299d3c5a64dd5ef5bacf71c1fcd6ddf59be4+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr><tr>
  <th align="left">7645d55dc2e32e97d5a878116a6b8dfc51ae3fbb+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr><tr>
  <th align="left">ebf24725a3a8448dfde3d228f450b4b74c44f79a+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr><tr>
  <th align="left">a88fdb9c8fae3d579ebce5f9c8448089042df4b5+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr><tr>
  <th align="left">ec3bff494e349214b579162d162abc2e364772d9+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr><tr>
  <th align="left">71a26faea11029aaafe94d85e648bf3d6b97ece2+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr><tr>
  <th align="left">8939c3fc9b16bf12a63d59053b23a2b07050e658+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr><tr>
  <th align="left">d95e4d62fb51217f1e678547a0a2bb731ef029c8+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.34 MiB</td>
  <td align="right"><strong>1.15 MiB</strong></td>
</tr><tr>
  <th align="left">0814326da81627d28511b5e815a0bd97e3495fdd+dirty</th>
  <td align="right">3.19 MiB</td>
  <td align="right">4.35 MiB</td>
  <td align="right"><strong>1.16 MiB</strong></td>
</tr></table>
</details>

author_association: CONTRIBUTOR
user: login: krystofwoldrich
created_at: 2025-04-07T11:35:05Z
body: I think we should add `enableTakeScreenshot` (or similar) option for this, to allow users to configure one or the other or both screenshot buttons.
author_association: CONTRIBUTOR
user: login: antonis
created_at: 2025-04-07T15:30:42Z
body: > I think we should add enableTakeScreenshot (or similar) option for this, to allow users to configure one or the other or both screenshot buttons.

My thought was to just keep the js options but I agree that it makes a lot of sense to be more granular on mobile 👍 

Updated with 476d18151e6dc4bd93f511450da54c6516719de4

<details><summary>Adding some screenshots of the four different screen states for reference</summary>
<p>

| `enableScreenshot` (or `imagePicker` set) | `enableTakeScreenshot` |
|---|---|
|![Simulator Screenshot - iPhone 16e - 2025-04-07 at 18 17 59](https://github.com/user-attachments/assets/5f577011-afc7-493a-9532-b61698e1a310)|![Simulator Screenshot - iPhone 16e - 2025-04-07 at 18 20 05](https://github.com/user-attachments/assets/fbb829d1-61c6-471f-9f47-33788c2f9d93)|

|Both|Screenshot attached|
|---|---|
|![Simulator Screenshot - iPhone 16e - 2025-04-07 at 18 17 20](https://github.com/user-attachments/assets/9bd4def9-df49-45bd-bfbb-14c14840deaf)|![Simulator Screenshot - iPhone 16e - 2025-04-07 at 18 17 28](https://github.com/user-attachments/assets/b1cd4a5b-c347-4ca9-a728-1f26243d2f97)|

</p>
</details> 

author_association: CONTRIBUTOR