diff --git a/src/components/ContextMenuItem.js b/src/components/ContextMenuItem.js
index 339e36afd6eb..639742efa00d 100644
--- a/src/components/ContextMenuItem.js
+++ b/src/components/ContextMenuItem.js
@@ -7,6 +7,7 @@ import Icon from './Icon';
import styles from '../styles/styles';
import * as StyleUtils from '../styles/StyleUtils';
import getButtonState from '../libs/getButtonState';
+import withDelayToggleButtonState, {withDelayToggleButtonStatePropTypes} from './withDelayToggleButtonState';
const propTypes = {
/** Icon Component */
@@ -32,6 +33,8 @@ const propTypes = {
/** A description text to show under the title */
description: PropTypes.string,
+
+ ...withDelayToggleButtonStatePropTypes,
};
const defaultProps = {
@@ -45,25 +48,15 @@ const defaultProps = {
class ContextMenuItem extends Component {
constructor(props) {
super(props);
- this.state = {
- success: false,
- };
- this.triggerPressAndUpdateSuccess = this.triggerPressAndUpdateSuccess.bind(this);
- }
- componentWillUnmount() {
- if (!this.successResetTimer) {
- return;
- }
-
- clearTimeout(this.successResetTimer);
+ this.triggerPressAndUpdateSuccess = this.triggerPressAndUpdateSuccess.bind(this);
}
/**
- * Called on button press and mark the run
+ * Method to call parent onPress and toggleDelayButtonState
*/
triggerPressAndUpdateSuccess() {
- if (this.state.success) {
+ if (this.props.isDelayButtonStateComplete) {
return;
}
this.props.onPress();
@@ -71,18 +64,13 @@ class ContextMenuItem extends Component {
// We only set the success state when we have icon or text to represent the success state
// We may want to replace this check by checking the Result from OnPress Callback in future.
if (this.props.successIcon || this.props.successText) {
- this.setState({
- success: true,
- });
- if (this.props.autoReset) {
- this.successResetTimer = setTimeout(() => this.setState({success: false}), 1800);
- }
+ this.props.toggleDelayButtonState(this.props.autoReset);
}
}
render() {
- const icon = this.state.success ? this.props.successIcon || this.props.icon : this.props.icon;
- const text = this.state.success ? this.props.successText || this.props.text : this.props.text;
+ const icon = this.props.isDelayButtonStateComplete ? this.props.successIcon || this.props.icon : this.props.icon;
+ const text = this.props.isDelayButtonStateComplete ? this.props.successText || this.props.text : this.props.text;
return (
this.props.isMini
? (
@@ -94,14 +82,14 @@ class ContextMenuItem extends Component {
style={
({hovered, pressed}) => [
styles.reportActionContextMenuMiniButton,
- StyleUtils.getButtonBackgroundColorStyle(getButtonState(hovered, pressed, this.state.success)),
+ StyleUtils.getButtonBackgroundColorStyle(getButtonState(hovered, pressed, this.props.isDelayButtonStateComplete)),
]
}
>
{({hovered, pressed}) => (
)}
@@ -112,7 +100,7 @@ class ContextMenuItem extends Component {
icon={icon}
onPress={this.triggerPressAndUpdateSuccess}
wrapperStyle={styles.pr9}
- success={this.state.success}
+ success={this.props.isDelayButtonStateComplete}
description={this.props.description}
/>
)
@@ -123,4 +111,4 @@ class ContextMenuItem extends Component {
ContextMenuItem.propTypes = propTypes;
ContextMenuItem.defaultProps = defaultProps;
-export default ContextMenuItem;
+export default withDelayToggleButtonState(ContextMenuItem);
diff --git a/src/components/HeaderWithCloseButton.js b/src/components/HeaderWithCloseButton.js
index ef8588709c34..8b83e61ac279 100755
--- a/src/components/HeaderWithCloseButton.js
+++ b/src/components/HeaderWithCloseButton.js
@@ -1,7 +1,7 @@
-import React from 'react';
+import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {
- View, TouchableOpacity, Keyboard,
+ View, Keyboard, Pressable,
} from 'react-native';
import styles from '../styles/styles';
import Header from './Header';
@@ -13,6 +13,10 @@ import withLocalize, {withLocalizePropTypes} from './withLocalize';
import Tooltip from './Tooltip';
import ThreeDotsMenu, {ThreeDotsMenuItemPropTypes} from './ThreeDotsMenu';
import VirtualKeyboard from '../libs/VirtualKeyboard';
+import getButtonState from '../libs/getButtonState';
+import * as StyleUtils from '../styles/StyleUtils';
+import withDelayToggleButtonState, {withDelayToggleButtonStatePropTypes} from './withDelayToggleButtonState';
+import compose from '../libs/compose';
const propTypes = {
/** Title of the Header */
@@ -75,6 +79,8 @@ const propTypes = {
}),
...withLocalizePropTypes,
+
+ ...withDelayToggleButtonStatePropTypes,
};
const defaultProps = {
@@ -100,94 +106,123 @@ const defaultProps = {
},
};
-const HeaderWithCloseButton = props => (
-
-
- {props.shouldShowBackButton && (
-
- {
- if (VirtualKeyboard.isOpen()) {
- Keyboard.dismiss();
- }
- props.onBackButtonPress();
- }}
- style={[styles.touchableButtonImage]}
- >
-
-
-
- )}
-
-
- {
- props.shouldShowDownloadButton && (
-
-
-
-
-
-
- )
- }
-
- {props.shouldShowGetAssistanceButton
- && (
-
- Navigation.navigate(ROUTES.getGetAssistanceRoute(props.guidesCallTaskID))}
- style={[styles.touchableButtonImage, styles.mr0]}
- accessibilityRole="button"
- accessibilityLabel={props.translate('getAssistancePage.questionMarkButtonTooltip')}
- >
-
-
-
- )}
-
- {props.shouldShowThreeDotsButton && (
-
+
+ {this.props.shouldShowBackButton && (
+
+ {
+ if (VirtualKeyboard.isOpen()) {
+ Keyboard.dismiss();
+ }
+ this.props.onBackButtonPress();
+ }}
+ style={[styles.touchableButtonImage]}
+ >
+
+
+
+ )}
+
- )}
-
- {props.shouldShowCloseButton
- && (
-
-
-
-
-
- )}
+
+ {
+ this.props.shouldShowDownloadButton && (
+
+
+
+
+
+
+ )
+ }
+
+ {this.props.shouldShowGetAssistanceButton
+ && (
+
+ Navigation.navigate(ROUTES.getGetAssistanceRoute(this.props.guidesCallTaskID))}
+ style={[styles.touchableButtonImage, styles.mr0]}
+ accessibilityRole="button"
+ accessibilityLabel={this.props.translate('getAssistancePage.questionMarkButtonTooltip')}
+ >
+
+
+
+ )}
+
+ {this.props.shouldShowThreeDotsButton && (
+
+ )}
+
+ {this.props.shouldShowCloseButton
+ && (
+
+
+
+
+
+ )}
+
+
-
-
-);
+ );
+ }
+}
HeaderWithCloseButton.propTypes = propTypes;
HeaderWithCloseButton.defaultProps = defaultProps;
HeaderWithCloseButton.displayName = 'HeaderWithCloseButton';
-export default withLocalize(HeaderWithCloseButton);
+export default compose(
+ withLocalize,
+ withDelayToggleButtonState,
+)(HeaderWithCloseButton);
diff --git a/src/components/withDelayToggleButtonState.js b/src/components/withDelayToggleButtonState.js
new file mode 100644
index 000000000000..c312d18fba74
--- /dev/null
+++ b/src/components/withDelayToggleButtonState.js
@@ -0,0 +1,82 @@
+import React, {Component} from 'react';
+import PropTypes from 'prop-types';
+import getComponentDisplayName from '../libs/getComponentDisplayName';
+
+const withDelayToggleButtonStatePropTypes = {
+ /** A value whether the button state is complete */
+ isDelayButtonStateComplete: PropTypes.bool.isRequired,
+
+ /** A function to call to change the complete state */
+ toggleDelayButtonState: PropTypes.func.isRequired,
+};
+
+export default function (WrappedComponent) {
+ class WithDelayToggleButtonState extends Component {
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ isDelayButtonStateComplete: false,
+ };
+ this.toggleDelayButtonState = this.toggleDelayButtonState.bind(this);
+ }
+
+ componentWillUnmount() {
+ if (!this.resetButtonStateCompleteTimer) {
+ return;
+ }
+
+ clearTimeout(this.resetButtonStateCompleteTimer);
+ }
+
+ /**
+ * @param {Boolean} resetAfterDelay Impose delay before toggling state
+ */
+ toggleDelayButtonState(resetAfterDelay) {
+ this.setState({
+ isDelayButtonStateComplete: true,
+ });
+
+ if (!resetAfterDelay) {
+ return;
+ }
+
+ this.resetButtonStateCompleteTimer = setTimeout(() => {
+ this.setState({
+ isDelayButtonStateComplete: false,
+ });
+ }, 1800);
+ }
+
+ render() {
+ return (
+
+ );
+ }
+ }
+
+ WithDelayToggleButtonState.displayName = `WithDelayToggleButtonState(${getComponentDisplayName(WrappedComponent)})`;
+ WithDelayToggleButtonState.propTypes = {
+ forwardedRef: PropTypes.oneOfType([
+ PropTypes.func,
+ PropTypes.shape({current: PropTypes.instanceOf(React.Component)}),
+ ]),
+ };
+ WithDelayToggleButtonState.defaultProps = {
+ forwardedRef: undefined,
+ };
+
+ return React.forwardRef((props, ref) => (
+ // eslint-disable-next-line react/jsx-props-no-spreading
+
+ ));
+}
+
+export {
+ withDelayToggleButtonStatePropTypes,
+};