diff --git a/src/CONST.js b/src/CONST.js
index 906d90effbc9..8da883e8a9f3 100644
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -29,6 +29,7 @@ const CONST = {
},
MODAL: {
MODAL_TYPE: {
+ CONFIRM: 'confirm',
CENTERED: 'centered',
BOTTOM_DOCKED: 'bottom_docked',
POPOVER: 'popover',
diff --git a/src/components/ConfirmModal.js b/src/components/ConfirmModal.js
new file mode 100644
index 000000000000..2e10bb1fddf0
--- /dev/null
+++ b/src/components/ConfirmModal.js
@@ -0,0 +1,90 @@
+import React from 'react';
+import {
+ TouchableOpacity, Text, View,
+} from 'react-native';
+import PropTypes from 'prop-types';
+import Header from './Header';
+import Modal from './Modal';
+import styles from '../styles/styles';
+import CONST from '../CONST';
+import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';
+
+const propTypes = {
+ /** Title of the modal */
+ title: PropTypes.string.isRequired,
+
+ /** A callback to call when the form has been submitted */
+ onConfirm: PropTypes.func.isRequired,
+
+ /** A callback to call when the form has been closed */
+ onCancel: PropTypes.func.isRequired,
+
+ /** Modal visibility */
+ isVisible: PropTypes.bool.isRequired,
+
+ /** Confirm button text */
+ confirmText: PropTypes.string,
+
+ /** Cancel button text */
+ cancelText: PropTypes.string,
+
+ /** Modal content text */
+ prompt: PropTypes.string,
+
+ ...windowDimensionsPropTypes,
+};
+
+const defaultProps = {
+ confirmText: 'Yes',
+ cancelText: 'No',
+ prompt: '',
+};
+
+const ConfirmModal = props => (
+
+
+
+
+
+
+
+ {props.prompt}
+
+
+
+
+ {props.confirmText}
+
+
+
+
+
+ {props.cancelText}
+
+
+
+
+);
+
+ConfirmModal.propTypes = propTypes;
+ConfirmModal.defaultProps = defaultProps;
+ConfirmModal.displayName = 'ConfirmModal';
+export default withWindowDimensions(ConfirmModal);
diff --git a/src/components/Modal/ModalPropTypes.js b/src/components/Modal/ModalPropTypes.js
index 565b9dbaf47b..54d509921552 100644
--- a/src/components/Modal/ModalPropTypes.js
+++ b/src/components/Modal/ModalPropTypes.js
@@ -20,6 +20,7 @@ const propTypes = {
// Style of modal to display
type: PropTypes.oneOf([
+ CONST.MODAL.MODAL_TYPE.CONFIRM,
CONST.MODAL.MODAL_TYPE.CENTERED,
CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED,
CONST.MODAL.MODAL_TYPE.POPOVER,
diff --git a/src/components/UpdateAppModal/BaseUpdateAppModal.js b/src/components/UpdateAppModal/BaseUpdateAppModal.js
index 3741996d3159..e547c460e95f 100644
--- a/src/components/UpdateAppModal/BaseUpdateAppModal.js
+++ b/src/components/UpdateAppModal/BaseUpdateAppModal.js
@@ -1,11 +1,6 @@
import React, {PureComponent} from 'react';
-import {
- TouchableOpacity, Text,
-} from 'react-native';
-import HeaderWithCloseButton from '../HeaderWithCloseButton';
-import Modal from '../Modal';
-import styles from '../../styles/styles';
import {propTypes, defaultProps} from './UpdateAppModalPropTypes';
+import ConfirmModal from '../ConfirmModal';
class BaseUpdateAppModal extends PureComponent {
constructor(props) {
@@ -29,36 +24,16 @@ class BaseUpdateAppModal extends PureComponent {
render() {
return (
<>
- this.setState({isModalOpen: false})}
+
- this.setState({isModalOpen: false})}
- />
-
- A new version of Expensify.cash is available.
- Update now or restart the app at a later time to download the latest changes.
-
- {this.props.onSubmit && (
-
-
- Update App
-
-
- )}
-
+ onConfirm={this.submitAndClose}
+ onCancel={() => this.setState({isModalOpen: false})}
+ prompt="A new version of Expensify.cash is available.
+ Update now or restart the app at a later time to download the latest changes."
+ confirmText="Update App"
+ cancelText="Cancel"
+ />
>
);
}
diff --git a/src/styles/getModalStyles.js b/src/styles/getModalStyles.js
index dc5319b441a1..f3ab417db1a4 100644
--- a/src/styles/getModalStyles.js
+++ b/src/styles/getModalStyles.js
@@ -19,6 +19,36 @@ export default (type, windowDimensions, popoverAnchorPosition = {}) => {
let shouldAddTopSafeAreaPadding = false;
switch (type) {
+ case CONST.MODAL.MODAL_TYPE.CONFIRM:
+ // A confirm modal is one that has a visible backdrop
+ // and can be dismissed by clicking outside of the modal.
+ modalStyle = {
+ ...modalStyle,
+ ...{
+ alignItems: 'center',
+ },
+ };
+ modalContainerStyle = {
+ // Shadow Styles
+ shadowColor: colors.black,
+ shadowOffset: {
+ width: 0,
+ height: 0,
+ },
+ shadowOpacity: 0.1,
+ shadowRadius: 5,
+
+ borderRadius: 12,
+ overflow: 'hidden',
+ width: variables.sideBarWidth,
+ };
+
+ // setting this to undefined we effectively disable the
+ // ability to swipe our modal
+ swipeDirection = undefined;
+ animationIn = 'fadeIn';
+ animationOut = 'fadeOut';
+ break;
case CONST.MODAL.MODAL_TYPE.CENTERED:
// A centered modal is one that has a visible backdrop
// and can be dismissed by clicking outside of the modal.
diff --git a/src/styles/utilities/spacing.js b/src/styles/utilities/spacing.js
index ba8b03f522f3..2fe247fecdcb 100644
--- a/src/styles/utilities/spacing.js
+++ b/src/styles/utilities/spacing.js
@@ -13,6 +13,14 @@ export default {
margin: 8,
},
+ m4: {
+ margin: 16,
+ },
+
+ m5: {
+ margin: 20,
+ },
+
mh1: {
marginHorizontal: 4,
},