From 54c2cc6282e3a0b5d014df0b5a2b395e08eb6392 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 3 Mar 2023 11:53:00 -0800 Subject: [PATCH 1/2] Wrap with a TestToolsGesture detector on dev only --- src/components/ScreenWrapper/index.js | 20 ++-------- src/components/TestToolsGestureDetector.js | 45 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 17 deletions(-) create mode 100644 src/components/TestToolsGestureDetector.js diff --git a/src/components/ScreenWrapper/index.js b/src/components/ScreenWrapper/index.js index 3b4dec0f9561..284faeacd5d3 100644 --- a/src/components/ScreenWrapper/index.js +++ b/src/components/ScreenWrapper/index.js @@ -1,6 +1,5 @@ import {View} from 'react-native'; import React from 'react'; -import {GestureDetector, Gesture} from 'react-native-gesture-handler'; import _ from 'underscore'; import {withOnyx} from 'react-native-onyx'; import KeyboardAvoidingView from '../KeyboardAvoidingView'; @@ -17,9 +16,9 @@ import withEnvironment from '../withEnvironment'; import ONYXKEYS from '../../ONYXKEYS'; import {withNetwork} from '../OnyxProvider'; import {propTypes, defaultProps} from './propTypes'; -import * as App from '../../libs/actions/App'; import SafeAreaConsumer from '../SafeAreaConsumer'; import TestToolsModal from '../TestToolsModal'; +import TestToolsGestureDetector from '../TestToolsGestureDetector'; class ScreenWrapper extends React.Component { constructor(props) { @@ -76,19 +75,6 @@ class ScreenWrapper extends React.Component { } render() { - // Open the test tools menu on 5 taps in dev only - const isDevEnvironment = this.props.environment === CONST.ENVIRONMENT.DEV; - const quintupleTap = Gesture.Tap() - .numberOfTaps(5) - - // Run the callbacks on the JS thread otherwise there's an error on iOS - .runOnJS(true) - .onEnd(() => { - if (!isDevEnvironment) { - return; - } - App.toggleTestToolsModal(); - }); return ( {({ @@ -106,7 +92,7 @@ class ScreenWrapper extends React.Component { } return ( - + - + ); }} diff --git a/src/components/TestToolsGestureDetector.js b/src/components/TestToolsGestureDetector.js new file mode 100644 index 000000000000..9bd97accfe87 --- /dev/null +++ b/src/components/TestToolsGestureDetector.js @@ -0,0 +1,45 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {GestureDetector, Gesture} from 'react-native-gesture-handler'; +import CONST from '../CONST'; +import withEnvironment, {environmentPropTypes} from './withEnvironment'; +import * as App from '../libs/actions/App'; + +/** + * If we are in the dev environment wrap the children in a gesture detector that opens a test tools modal after 5 taps + */ + +const propTypes = { + /** Children to wrap in TestToolsGestureDetector. */ + children: PropTypes.node.isRequired, + + ...environmentPropTypes, +}; + +const TestToolsGestureDetector = (props) => { + const quintupleTap = Gesture.Tap() + .numberOfTaps(5) + + // Run the callbacks on the JS thread otherwise there's an error on iOS + .runOnJS(true) + .onEnd(App.toggleTestToolsModal); + + // The gesture to open the test tools menu should only exist in the dev environment + if (props.environment === CONST.ENVIRONMENT.DEV) { + return ( + + {props.children} + + ); + } + return ( + <> + {props.children} + + ); +}; + +TestToolsGestureDetector.propTypes = propTypes; +TestToolsGestureDetector.displayName = 'TestToolsGestureDetector'; + +export default withEnvironment(TestToolsGestureDetector); From 438678662466d717c033881ac90520d6ffb04a13 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 3 Mar 2023 12:30:32 -0800 Subject: [PATCH 2/2] Restore previous work This reverts commit 5cbcfbbf12b229a846a6ff59b9ec1ac39014313e. --- src/CONST.js | 2 + src/ONYXKEYS.js | 3 ++ src/components/ScreenWrapper/index.js | 5 +++ src/components/ScreenWrapper/propTypes.js | 7 +++ src/components/TestToolMenu.js | 2 +- src/components/TestToolRow.js | 2 +- src/components/TestToolsModal.js | 44 +++++++++++++++++++ src/libs/actions/App.js | 17 +++++++ .../getModalStyles/getBaseModalStyles.js | 31 +++++++++++++ src/styles/utilities/sizing.js | 4 ++ 10 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 src/components/TestToolsModal.js diff --git a/src/CONST.js b/src/CONST.js index 26acb0412305..93fc7e222945 100755 --- a/src/CONST.js +++ b/src/CONST.js @@ -375,6 +375,7 @@ const CONST = { CONFIRM: 'confirm', CENTERED: 'centered', CENTERED_UNSWIPEABLE: 'centered_unswipeable', + CENTERED_SMALL: 'centered_small', BOTTOM_DOCKED: 'bottom_docked', POPOVER: 'popover', RIGHT_DOCKED: 'right_docked', @@ -400,6 +401,7 @@ const CONST = { WARM: 'warm', REPORT_ACTION_ITEM_LAYOUT_DEBOUNCE_TIME: 1500, SHOW_LOADING_SPINNER_DEBOUNCE_TIME: 250, + TEST_TOOLS_MODAL_THROTTLE_TIME: 800, TOOLTIP_SENSE: 1000, TRIE_INITIALIZATION: 'trie_initialization', COMMENT_LENGTH_DEBOUNCE_TIME: 500, diff --git a/src/ONYXKEYS.js b/src/ONYXKEYS.js index 9cb0d62731d1..fd61c0f8bc5c 100755 --- a/src/ONYXKEYS.js +++ b/src/ONYXKEYS.js @@ -170,6 +170,9 @@ export default { // Is Keyboard shortcuts modal open? IS_SHORTCUTS_MODAL_OPEN: 'isShortcutsModalOpen', + // Is the test tools modal open? + IS_TEST_TOOLS_MODAL_OPEN: 'isTestToolsModalOpen', + // Stores information about active wallet transfer amount, selectedAccountID, status, etc WALLET_TRANSFER: 'walletTransfer', diff --git a/src/components/ScreenWrapper/index.js b/src/components/ScreenWrapper/index.js index bad5a545daba..8fbb60428e5d 100644 --- a/src/components/ScreenWrapper/index.js +++ b/src/components/ScreenWrapper/index.js @@ -13,6 +13,7 @@ import OfflineIndicator from '../OfflineIndicator'; import compose from '../../libs/compose'; import withNavigation from '../withNavigation'; import withWindowDimensions from '../withWindowDimensions'; +import withEnvironment from '../withEnvironment'; import ONYXKEYS from '../../ONYXKEYS'; import {withNetwork} from '../OnyxProvider'; import {propTypes, defaultProps} from './propTypes'; @@ -157,6 +158,10 @@ export default compose( modal: { key: ONYXKEYS.MODAL, }, + isTestToolsModalOpen: { + key: ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN, + }, }), withNetwork(), + withEnvironment, )(ScreenWrapper); diff --git a/src/components/ScreenWrapper/propTypes.js b/src/components/ScreenWrapper/propTypes.js index 4345f60fad48..5f0e913a5980 100644 --- a/src/components/ScreenWrapper/propTypes.js +++ b/src/components/ScreenWrapper/propTypes.js @@ -1,4 +1,5 @@ import PropTypes from 'prop-types'; +import {environmentPropTypes} from '../withEnvironment'; const propTypes = { /** Array of additional styles to add */ @@ -19,6 +20,9 @@ const propTypes = { // Called when navigated Screen's transition is finished. It does not fire when user exit the page. onEntryTransitionEnd: PropTypes.func, + // Is the test tools modal open? + isTestToolsModalOpen: PropTypes.bool, + /** The behavior to pass to the KeyboardAvoidingView, requires some trial and error depending on the layout/devices used. * Search 'switch(behavior)' in ./node_modules/react-native/Libraries/Components/Keyboard/KeyboardAvoidingView.js for more context */ keyboardAvoidingViewBehavior: PropTypes.oneOf(['padding', 'height', 'position']), @@ -31,6 +35,8 @@ const propTypes = { /** Whether to dismiss keyboard before leaving a screen */ shouldDismissKeyboardBeforeClose: PropTypes.bool, + + ...environmentPropTypes, }; const defaultProps = { @@ -40,6 +46,7 @@ const defaultProps = { includePaddingTop: true, onEntryTransitionEnd: () => {}, modal: {}, + isTestToolsModalOpen: false, keyboardAvoidingViewBehavior: 'padding', }; diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index a5e61942f240..ec99689a05f6 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -37,7 +37,7 @@ const defaultProps = { const TestToolMenu = props => ( <> - + Test Preferences diff --git a/src/components/TestToolRow.js b/src/components/TestToolRow.js index 5364f44537b0..deefaaf3adc0 100644 --- a/src/components/TestToolRow.js +++ b/src/components/TestToolRow.js @@ -13,7 +13,7 @@ const propTypes = { }; const TestToolRow = props => ( - + {props.title} diff --git a/src/components/TestToolsModal.js b/src/components/TestToolsModal.js new file mode 100644 index 000000000000..92aae8e3c810 --- /dev/null +++ b/src/components/TestToolsModal.js @@ -0,0 +1,44 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {withOnyx} from 'react-native-onyx'; +import {View} from 'react-native'; +import ONYXKEYS from '../ONYXKEYS'; +import Modal from './Modal'; +import CONST from '../CONST'; +import * as App from '../libs/actions/App'; +import TestToolMenu from './TestToolMenu'; +import styles from '../styles/styles'; + +const propTypes = { + /** Whether the test tools modal is open */ + isTestToolsModalOpen: PropTypes.bool, +}; + +const defaultProps = { + isTestToolsModalOpen: false, +}; + +const TestToolsModal = props => ( + + + + + +); + +TestToolsModal.propTypes = propTypes; +TestToolsModal.defaultProps = defaultProps; +TestToolsModal.displayName = 'TestToolsModal'; + +export default withOnyx({ + modal: { + key: ONYXKEYS.MODAL, + }, + isTestToolsModalOpen: { + key: ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN, + }, +})(TestToolsModal); diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js index b3d05bed7f6a..7f08b7a0a836 100644 --- a/src/libs/actions/App.js +++ b/src/libs/actions/App.js @@ -286,6 +286,22 @@ function openProfile() { Navigation.navigate(ROUTES.SETTINGS_PROFILE); } +let isTestToolsModalOpen = false; +Onyx.connect({ + key: ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN, + callback: val => isTestToolsModalOpen = val || false, +}); + +/** + * Toggle the test tools modal open or closed. Throttle the toggle to fix Android Chrome where there seems to be an extra tap which closes the modal. + * Throttling also makes the modal stay open if you accidentally tap an extra time, which is easy to do. + */ +function toggleTestToolsModal() { + const toggle = () => Onyx.set(ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN, !isTestToolsModalOpen); + const throttledToggle = _.throttle(toggle, CONST.TIMING.TEST_TOOLS_MODAL_THROTTLE_TIME); + throttledToggle(); +} + export { setLocale, setLocaleAndNavigate, @@ -294,4 +310,5 @@ export { openProfile, openApp, reconnectApp, + toggleTestToolsModal, }; diff --git a/src/styles/getModalStyles/getBaseModalStyles.js b/src/styles/getModalStyles/getBaseModalStyles.js index 36c98880f69a..0475635a35f5 100644 --- a/src/styles/getModalStyles/getBaseModalStyles.js +++ b/src/styles/getModalStyles/getBaseModalStyles.js @@ -124,6 +124,37 @@ export default (type, windowDimensions, popoverAnchorPosition = {}, innerContain shouldAddTopSafeAreaPadding = isSmallScreenWidth; shouldAddBottomSafeAreaPadding = false; break; + case CONST.MODAL.MODAL_TYPE.CENTERED_SMALL: + // A centered modal that takes up the minimum possible screen space on all devices + modalStyle = { + ...modalStyle, + ...{ + alignItems: 'center', + }, + }; + modalContainerStyle = { + // Shadow Styles + shadowColor: themeColors.shadow, + shadowOffset: { + width: 0, + height: 0, + }, + shadowOpacity: 0.1, + shadowRadius: 5, + + borderRadius: 12, + borderWidth: 0, + }; + + // Allow this modal to be dismissed with a swipe down or swipe right + swipeDirection = ['down', 'right']; + animationIn = 'fadeIn'; + animationOut = 'fadeOut'; + shouldAddTopSafeAreaMargin = false; + shouldAddBottomSafeAreaMargin = false; + shouldAddTopSafeAreaPadding = false; + shouldAddBottomSafeAreaPadding = false; + break; case CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED: modalStyle = { ...modalStyle, diff --git a/src/styles/utilities/sizing.js b/src/styles/utilities/sizing.js index a55774756075..1051098fbe16 100644 --- a/src/styles/utilities/sizing.js +++ b/src/styles/utilities/sizing.js @@ -28,6 +28,10 @@ export default { minWidth: '25%', }, + mnw120: { + minWidth: 120, + }, + w50: { width: '50%', },