From 638377d3b2d5ed2a20a5813ae630a59ad60fdb27 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Thu, 23 Jan 2025 16:09:16 +0200 Subject: [PATCH 01/18] Auto-inject feedback form --- .../src/js/feedback/FeedbackFormManager.tsx | 92 +++++++++++++++++++ packages/core/src/js/index.ts | 1 + packages/core/src/js/sdk.tsx | 5 +- .../react-native/src/Screens/ErrorsScreen.tsx | 6 ++ 4 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/js/feedback/FeedbackFormManager.tsx diff --git a/packages/core/src/js/feedback/FeedbackFormManager.tsx b/packages/core/src/js/feedback/FeedbackFormManager.tsx new file mode 100644 index 0000000000..0b82e61693 --- /dev/null +++ b/packages/core/src/js/feedback/FeedbackFormManager.tsx @@ -0,0 +1,92 @@ +import * as React from 'react'; +import { Modal, StyleSheet,View } from 'react-native'; + +import { FeedbackForm } from './FeedbackForm'; + +class FeedbackFormManager { + private static _isVisible = false; + private static _setVisibility: (visible: boolean) => void; + + public static initialize(setVisibility: (visible: boolean) => void): void { + this._setVisibility = setVisibility; + } + + public static show(): void { + if (this._setVisibility) { + this._isVisible = true; + this._setVisibility(true); + } + } + + public static hide(): void { + if (this._setVisibility) { + this._isVisible = false; + this._setVisibility(false); + } + } + + public static isFormVisible(): boolean { + return this._isVisible; + } +} + +interface FeedbackFormProviderProps { + children: React.ReactNode; +} + +class FeedbackFormProvider extends React.Component { + public state = { + isVisible: false, + }; + + public constructor(props: FeedbackFormProviderProps) { + super(props); + FeedbackFormManager.initialize(this._setVisibilityFunction); + } + + /** + * Renders the feedback form modal. + */ + public render(): React.ReactNode { + const { isVisible } = this.state; + + return ( + <> + {this.props.children} + {isVisible && ( + + + + + + )} + + ); + } + + private _setVisibilityFunction = (visible: boolean): void => { + this.setState({ isVisible: visible }); + }; + + private _handleClose = (): void => { + FeedbackFormManager.hide(); + this.setState({ isVisible: false }); + }; +} + +const showFeedbackForm = (): void => { + FeedbackFormManager.show(); +}; + +const styles = StyleSheet.create({ + modalBackground: { + flex: 1, + justifyContent: 'center', + backgroundColor: 'rgba(0,0,0,0.5)', + }, +}); + +export { showFeedbackForm, FeedbackFormProvider }; diff --git a/packages/core/src/js/index.ts b/packages/core/src/js/index.ts index 53abd065b8..a07e89f92a 100644 --- a/packages/core/src/js/index.ts +++ b/packages/core/src/js/index.ts @@ -86,3 +86,4 @@ export type { TimeToDisplayProps } from './tracing'; export { Mask, Unmask } from './replay/CustomMask'; export { FeedbackForm } from './feedback/FeedbackForm'; +export { showFeedbackForm } from './feedback/FeedbackFormManager'; diff --git a/packages/core/src/js/sdk.tsx b/packages/core/src/js/sdk.tsx index 3c6fdff90c..606e2cf5ea 100644 --- a/packages/core/src/js/sdk.tsx +++ b/packages/core/src/js/sdk.tsx @@ -8,6 +8,7 @@ import { import * as React from 'react'; import { ReactNativeClient } from './client'; +import { FeedbackFormProvider } from './feedback/FeedbackFormManager'; import { getDevServer } from './integrations/debugsymbolicatorutils'; import { getDefaultIntegrations } from './integrations/default'; import type { ReactNativeClientOptions, ReactNativeOptions, ReactNativeWrapperOptions } from './options'; @@ -163,7 +164,9 @@ export function wrap

>( return ( - + + + ); diff --git a/samples/react-native/src/Screens/ErrorsScreen.tsx b/samples/react-native/src/Screens/ErrorsScreen.tsx index 4788fa407a..cc2810fd1d 100644 --- a/samples/react-native/src/Screens/ErrorsScreen.tsx +++ b/samples/react-native/src/Screens/ErrorsScreen.tsx @@ -226,6 +226,12 @@ const ErrorsScreen = (_props: Props) => { _props.navigation.navigate('FeedbackForm'); }} /> +