Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open a test tools modal with 5 taps on dev #13900

Merged
merged 22 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ede8ea5
Initial quintuple tap gesture on header view
neil-marcellini Dec 30, 2022
83f8d9a
Move quintuple tap gesture into the screen wrapper
neil-marcellini Dec 30, 2022
a6d7586
Add a small centered modal type
neil-marcellini Jan 6, 2023
e5c4141
Use Onyx to open and close the test tools modal
neil-marcellini Jan 6, 2023
3065c6c
Blank test tools modal in the screen wrapper
neil-marcellini Jan 6, 2023
eb2573c
Create a test tools modal
neil-marcellini Jan 6, 2023
3d6fbc7
Open the test tools menu on 5 taps in dev only
neil-marcellini Jan 6, 2023
933d994
Only render the test tools modal on dev
neil-marcellini Jan 6, 2023
bea47c8
Fix the gesture onEnd callback
neil-marcellini Jan 6, 2023
c762879
Fix iOS by running callbacks on the JS thread
neil-marcellini Jan 6, 2023
73c635c
Somewhat fix the iOS modal
neil-marcellini Jan 7, 2023
9d18e53
Merge branch 'main' into neil-test-tool-gesture
neil-marcellini Jan 10, 2023
75d30f7
Min width for mobile test tool modal
neil-marcellini Feb 8, 2023
2a99b12
Merge branch 'main' into neil-test-tool-gesture
neil-marcellini Feb 8, 2023
b9a901b
lint
neil-marcellini Feb 8, 2023
ffd6288
Clean up
neil-marcellini Feb 8, 2023
257e1b2
Add missing prop type
neil-marcellini Feb 8, 2023
40105a4
Standardize on TestToolsModal name
neil-marcellini Feb 8, 2023
0d3c1c6
Fix test tools modal after merge
neil-marcellini Feb 8, 2023
f598264
Remove extra top margin
neil-marcellini Feb 8, 2023
f3fb8ab
Throttle toggling test tools modal for mWeb Chrome
neil-marcellini Feb 18, 2023
eca2c73
Use constant for test tools modal throttle time
neil-marcellini Feb 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,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',
Expand Down
3 changes: 3 additions & 0 deletions src/ONYXKEYS.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,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',

Expand Down
70 changes: 47 additions & 23 deletions src/components/ScreenWrapper/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
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';
Expand All @@ -12,10 +13,13 @@ 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';
import * as App from '../../libs/actions/App';
import SafeAreaConsumer from '../SafeAreaConsumer';
import TestToolsModal from '../TestToolsModal';

class ScreenWrapper extends React.Component {
constructor(props) {
Expand Down Expand Up @@ -72,6 +76,19 @@ 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;
Copy link
Collaborator

@mananjadhav mananjadhav Feb 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@neil-marcellini Should this be here or still an outer layer?

I tried the taps on Login page and it didn't work? Now I am not sure if we would even need it there, but we do have controls like sign-in and language change which cannot be tested offline if the Test modal won't show up.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. It will be good to place it in a more outer layer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this to the ScreenWrapper since it appears to wrap almost every page. The public screens that have content other than a loading indicator, such as the SetPasswordPage and the SignInPage, do not use the screen wrapper.

I could try to use the ScreenWrapper on these pages but I would have to test how that works. Alternatively I could create another wrapper component specifically for this gesture and use it on these public pages as well in the screen wrapper.

I think it's relatively rare to test changing offline state on the public screens, so maybe I could implement that with a follow up PR sometime next week? Does that work for you guys?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah a follow up PR sounds okay to me.

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.openTestToolsModal();
});
return (
<SafeAreaConsumer>
{({
Expand All @@ -89,29 +106,32 @@ class ScreenWrapper extends React.Component {
}

return (
<View
style={[
...this.props.style,
styles.flex1,
paddingStyle,
]}
>
<KeyboardAvoidingView style={[styles.w100, styles.h100, {maxHeight: this.props.windowHeight}]} behavior={this.props.keyboardAvoidingViewBehavior}>
<HeaderGap />
{// If props.children is a function, call it to provide the insets to the children.
_.isFunction(this.props.children)
? this.props.children({
insets,
safeAreaPaddingBottomStyle,
didScreenTransitionEnd: this.state.didScreenTransitionEnd,
})
: this.props.children
}
{this.props.isSmallScreenWidth && (
<OfflineIndicator />
)}
</KeyboardAvoidingView>
</View>
<GestureDetector gesture={quintupleTap}>
<View
style={[
...this.props.style,
styles.flex1,
paddingStyle,
]}
>
<KeyboardAvoidingView style={[styles.w100, styles.h100, {maxHeight: this.props.windowHeight}]} behavior={this.props.keyboardAvoidingViewBehavior}>
<HeaderGap />
{(this.props.environment === CONST.ENVIRONMENT.DEV) && <TestToolsModal />}
{// If props.children is a function, call it to provide the insets to the children.
_.isFunction(this.props.children)
? this.props.children({
insets,
safeAreaPaddingBottomStyle,
didScreenTransitionEnd: this.state.didScreenTransitionEnd,
})
: this.props.children
}
{this.props.isSmallScreenWidth && (
<OfflineIndicator />
)}
</KeyboardAvoidingView>
</View>
</GestureDetector>
);
}}
</SafeAreaConsumer>
Expand All @@ -129,6 +149,10 @@ export default compose(
modal: {
key: ONYXKEYS.MODAL,
},
isTestToolsModalOpen: {
key: ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN,
},
}),
withNetwork(),
withEnvironment,
)(ScreenWrapper);
7 changes: 7 additions & 0 deletions src/components/ScreenWrapper/propTypes.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
import {environmentPropTypes} from '../withEnvironment';

const propTypes = {
/** Array of additional styles to add */
Expand All @@ -19,6 +20,9 @@ const propTypes = {
// Called when navigated Screen's transition is finished.
onTransitionEnd: 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']),
Expand All @@ -28,6 +32,8 @@ const propTypes = {
/** Indicates when an Alert modal is about to be visible */
willAlertModalBecomeVisible: PropTypes.bool,
}),

...environmentPropTypes,
};

const defaultProps = {
Expand All @@ -36,6 +42,7 @@ const defaultProps = {
includePaddingTop: true,
onTransitionEnd: () => {},
modal: {},
isTestToolsModalOpen: false,
keyboardAvoidingViewBehavior: 'padding',
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/TestToolMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const defaultProps = {

const TestToolMenu = props => (
<>
<Text style={[styles.textLabelSupporting, styles.mb2, styles.mt6]} numberOfLines={1}>
<Text style={[styles.textLabelSupporting, styles.mb2]} numberOfLines={1}>
Test Preferences
</Text>

Expand Down
2 changes: 1 addition & 1 deletion src/components/TestToolRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const propTypes = {
};

const TestToolRow = props => (
<View style={[styles.flexRow, styles.mb6, styles.justifyContentBetween, styles.alignItemsCenter]}>
<View style={[styles.flexRow, styles.mb6, styles.justifyContentBetween, styles.alignItemsCenter, styles.mnw120]}>
<View style={styles.flex2}>
<Text>
{props.title}
Expand Down
44 changes: 44 additions & 0 deletions src/components/TestToolsModal.js
Original file line number Diff line number Diff line change
@@ -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 => (
<Modal
isVisible={props.isTestToolsModalOpen}
type={CONST.MODAL.MODAL_TYPE.CENTERED_SMALL}
onClose={App.closeTestToolsModal}
>
<View style={[styles.settingsPageBody, styles.p5]}>
<TestToolMenu />
</View>
</Modal>
);

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);
10 changes: 10 additions & 0 deletions src/libs/actions/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,21 @@ function openProfile() {
Navigation.navigate(ROUTES.SETTINGS_PROFILE);
}

function openTestToolsModal() {
Onyx.set(ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN, true);
}

function closeTestToolsModal() {
Onyx.set(ONYXKEYS.IS_TEST_TOOLS_MODAL_OPEN, false);
}

export {
setLocale,
setSidebarLoaded,
setUpPoliciesAndNavigate,
openProfile,
openApp,
reconnectApp,
openTestToolsModal,
closeTestToolsModal,
};
31 changes: 31 additions & 0 deletions src/styles/getModalStyles/getBaseModalStyles.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,37 @@ export default (type, windowDimensions, popoverAnchorPosition = {}, containerSty
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,
Expand Down
4 changes: 4 additions & 0 deletions src/styles/utilities/sizing.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export default {
minWidth: '25%',
},

mnw120: {
minWidth: 120,
},

w50: {
width: '50%',
},
Expand Down