-
-
Notifications
You must be signed in to change notification settings - Fork 342
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Auto-inject feedback form * Temporarily disable sample rotating indicator * Revert "Temporarily disable sample rotating indicator" This reverts commit db407ce. * Wrap Modal in a View * Handles Android back button * Make modal style configurable * Print an error when the modal is not supported * Add changelog * Adds tests * Get major, minor version with deconstruct declaration Co-authored-by: LucasZF <[email protected]> * Remove if condition Co-authored-by: LucasZF <[email protected]> * Prettier * Fix test import --------- Co-authored-by: LucasZF <[email protected]>
- Loading branch information
1 parent
b7b36d8
commit eda1cb7
Showing
9 changed files
with
184 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { logger } from '@sentry/core'; | ||
import * as React from 'react'; | ||
import { Modal, View } from 'react-native'; | ||
|
||
import { FeedbackForm } from './FeedbackForm'; | ||
import defaultStyles from './FeedbackForm.styles'; | ||
import type { FeedbackFormStyles } from './FeedbackForm.types'; | ||
import { isModalSupported } from './utils'; | ||
|
||
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; | ||
styles?: FeedbackFormStyles; | ||
} | ||
|
||
class FeedbackFormProvider extends React.Component<FeedbackFormProviderProps> { | ||
public state = { | ||
isVisible: false, | ||
}; | ||
|
||
public constructor(props: FeedbackFormProviderProps) { | ||
super(props); | ||
FeedbackFormManager.initialize(this._setVisibilityFunction); | ||
} | ||
|
||
/** | ||
* Renders the feedback form modal. | ||
*/ | ||
public render(): React.ReactNode { | ||
if (!isModalSupported()) { | ||
logger.error('FeedbackForm Modal is not supported in React Native < 0.71 with Fabric renderer.'); | ||
return <>{this.props.children}</>; | ||
} | ||
|
||
const { isVisible } = this.state; | ||
const styles: FeedbackFormStyles = { ...defaultStyles, ...this.props.styles }; | ||
|
||
// Wrapping the `Modal` component in a `View` component is necessary to avoid | ||
// issues like https://github.com/software-mansion/react-native-reanimated/issues/6035 | ||
return ( | ||
<> | ||
{this.props.children} | ||
{isVisible && ( | ||
<View> | ||
<Modal visible={isVisible} transparent animationType="slide" onRequestClose={this._handleClose} testID="feedback-form-modal"> | ||
<View style={styles.modalBackground}> | ||
<FeedbackForm | ||
onFormClose={this._handleClose} | ||
onFormSubmitted={this._handleClose} | ||
/> | ||
</View> | ||
</Modal> | ||
</View> | ||
)} | ||
</> | ||
); | ||
} | ||
|
||
private _setVisibilityFunction = (visible: boolean): void => { | ||
this.setState({ isVisible: visible }); | ||
}; | ||
|
||
private _handleClose = (): void => { | ||
FeedbackFormManager.hide(); | ||
this.setState({ isVisible: false }); | ||
}; | ||
} | ||
|
||
const showFeedbackForm = (): void => { | ||
FeedbackFormManager.show(); | ||
}; | ||
|
||
export { showFeedbackForm, FeedbackFormProvider }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { logger } from '@sentry/core'; | ||
import { render } from '@testing-library/react-native'; | ||
import * as React from 'react'; | ||
import { Text } from 'react-native'; | ||
|
||
import { FeedbackFormProvider, showFeedbackForm } from '../../src/js/feedback/FeedbackFormManager'; | ||
import { isModalSupported } from '../../src/js/feedback/utils'; | ||
|
||
jest.mock('../../src/js/feedback/utils', () => ({ | ||
isModalSupported: jest.fn(), | ||
})); | ||
|
||
const mockedIsModalSupported = isModalSupported as jest.MockedFunction<typeof isModalSupported>; | ||
|
||
beforeEach(() => { | ||
logger.error = jest.fn(); | ||
}); | ||
|
||
describe('FeedbackFormManager', () => { | ||
it('showFeedbackForm displays the form when FeedbackFormProvider is used', () => { | ||
mockedIsModalSupported.mockReturnValue(true); | ||
const { getByText, getByTestId } = render( | ||
<FeedbackFormProvider> | ||
<Text>App Components</Text> | ||
</FeedbackFormProvider> | ||
); | ||
|
||
showFeedbackForm(); | ||
|
||
expect(getByTestId('feedback-form-modal')).toBeTruthy(); | ||
expect(getByText('App Components')).toBeTruthy(); | ||
}); | ||
|
||
it('showFeedbackForm does not display the form when Modal is not available', () => { | ||
mockedIsModalSupported.mockReturnValue(false); | ||
const { getByText, queryByTestId } = render( | ||
<FeedbackFormProvider> | ||
<Text>App Components</Text> | ||
</FeedbackFormProvider> | ||
); | ||
|
||
showFeedbackForm(); | ||
|
||
expect(queryByTestId('feedback-form-modal')).toBeNull(); | ||
expect(getByText('App Components')).toBeTruthy(); | ||
expect(logger.error).toHaveBeenLastCalledWith( | ||
'FeedbackForm Modal is not supported in React Native < 0.71 with Fabric renderer.', | ||
); | ||
}); | ||
|
||
it('showFeedbackForm does not throw an error when FeedbackFormProvider is not used', () => { | ||
expect(() => { | ||
showFeedbackForm(); | ||
}).not.toThrow(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters