Skip to content

Commit

Permalink
Network Specific Asset Education - Updated (#3910)
Browse files Browse the repository at this point in the history
* show network specific asset education modal when toggled to a network
Co-authored-by: Curtis <Curtis.David7@gmail.com>
  • Loading branch information
blackdevelopa authored Mar 28, 2022
1 parent 2daaf1d commit fa63312
Show file tree
Hide file tree
Showing 30 changed files with 774 additions and 24 deletions.
34 changes: 34 additions & 0 deletions app/actions/onboardNetwork/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Handle the onboarding network action
*
* @param {object} data object containing the event data
* @returns
*/
export const onboardNetworkAction = (data: string) => ({
type: 'NETWORK_ONBOARDED',
payload: data,
});

export const networkSwitched = ({ networkUrl, networkStatus }: { networkUrl: string; networkStatus: boolean }) => ({
type: 'NETWORK_SWITCHED',
networkUrl,
networkStatus,
});

export const showNetworkOnboardingAction = ({
networkUrl,
networkType,
nativeToken,
showNetworkOnboarding,
}: {
networkUrl: string;
networkType: string;
nativeToken: string;
showNetworkOnboarding: boolean;
}) => ({
type: 'SHOW_NETWORK_ONBOARDING',
networkUrl,
networkType,
nativeToken,
showNetworkOnboarding,
});
7 changes: 7 additions & 0 deletions app/components/Nav/Main/RootRPCMethodsUI.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { getTokenList } from '../../../reducers/tokens';
import { toLowerCaseEquals } from '../../../util/general';
import { ApprovalTypes } from '../../../core/RPCMethods/RPCMethodMiddleware';
import { mockTheme, useAppThemeFromContext } from '../../../util/theme';
import { networkSwitched } from '../../../actions/onboardNetwork';

const hstInterface = new ethers.utils.Interface(abi);

Expand Down Expand Up @@ -487,6 +488,7 @@ const RootRPCMethodsUI = (props) => {
const onSwitchCustomNetworkConfirm = () => {
setShowPendingApproval(false);
acceptPendingApproval(customNetworkToSwitch.id, customNetworkToSwitch.data);
props.networkSwitched({ networkUrl: customNetworkToSwitch.data.rpcUrl, networkStatus: true });
};

/**
Expand Down Expand Up @@ -718,6 +720,10 @@ RootRPCMethodsUI.propTypes = {
* Chain id
*/
chainId: PropTypes.string,
/**
* updates redux when network is switched
*/
networkSwitched: PropTypes.func,
};

const mapStateToProps = (state) => ({
Expand All @@ -735,6 +741,7 @@ const mapDispatchToProps = (dispatch) => ({
setTransactionObject: (transaction) => dispatch(setTransactionObject(transaction)),
toggleDappTransactionModal: (show = null) => dispatch(toggleDappTransactionModal(show)),
toggleApproveModal: (show) => dispatch(toggleApproveModal(show)),
networkSwitched: ({ networkUrl, networkStatus }) => dispatch(networkSwitched({ networkUrl, networkStatus })),
});

export default connect(mapStateToProps, mapDispatchToProps)(RootRPCMethodsUI);
106 changes: 97 additions & 9 deletions app/components/UI/DrawerView/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ import { getCurrentRoute } from '../../../reducers/navigation';
import { ScrollView } from 'react-native-gesture-handler';
import { isZero } from '../../../util/lodash';
import { ThemeContext, mockTheme } from '../../../util/theme';
import NetworkInfo from '../NetworkInfo';
import sanitizeUrl from '../../../util/sanitizeUrl';
import { onboardNetworkAction, networkSwitched } from '../../../actions/onboardNetwork';

const createStyles = (colors) =>
StyleSheet.create({
Expand Down Expand Up @@ -396,6 +399,26 @@ class DrawerView extends PureComponent {
* Latest navigation route
*/
currentRoute: PropTypes.string,
/**
* handles action for onboarding to a network
*/
onboardNetworkAction: PropTypes.func,
/**
* returns network onboarding state
*/
networkOnboarding: PropTypes.object,
/**
* returns switched network state
*/
switchedNetwork: PropTypes.object,
/**
* updates when network is switched
*/
networkSwitched: PropTypes.func,
/**
*
*/
networkOnboardedState: PropTypes.array,
};

state = {
Expand All @@ -406,6 +429,11 @@ class DrawerView extends PureComponent {
address: undefined,
currentNetwork: undefined,
},
networkSelected: false,
networkType: undefined,
networkCurrency: undefined,
showModal: false,
networkUrl: undefined,
};

browserSectionRef = React.createRef();
Expand Down Expand Up @@ -527,6 +555,22 @@ class DrawerView extends PureComponent {
}
};

onInfoNetworksModalClose = async (manualClose) => {
const {
networkOnboarding: { showNetworkOnboarding, networkUrl },
onboardNetworkAction,
switchedNetwork: { networkUrl: switchedNetworkUrl },
networkSwitched,
} = this.props;
this.setState({ networkSelected: !this.state.networkSelected, showModal: false });
!showNetworkOnboarding && this.toggleNetworksModal();
onboardNetworkAction(sanitizeUrl(networkUrl) || sanitizeUrl(switchedNetworkUrl) || this.state.networkUrl);
networkSwitched({ networkUrl: '', networkStatus: false });
if (!manualClose) {
await this.hideDrawer();
}
};

toggleNetworksModal = () => {
if (!this.animatingNetworksModal) {
this.animatingNetworksModal = true;
Expand All @@ -537,6 +581,19 @@ class DrawerView extends PureComponent {
}
};

onNetworkSelected = (type, currency, url) => {
this.setState({
networkType: type,
networkUrl: url || type,
networkCurrency: currency,
networkSelected: true,
});
};

switchModalContent = () => {
this.setState({ showModal: true });
};

showReceiveModal = () => {
this.toggleReceiveModal();
};
Expand Down Expand Up @@ -947,6 +1004,11 @@ class DrawerView extends PureComponent {
ticker,
seedphraseBackedUp,
currentRoute,
networkOnboarding,
networkOnboardedState,
switchedNetwork,
networkModalVisible,
navigation,
} = this.props;
const colors = this.context.colors || mockTheme.colors;
const styles = createStyles(colors);
Expand All @@ -955,6 +1017,8 @@ class DrawerView extends PureComponent {
invalidCustomNetwork,
showProtectWalletModal,
account: { name: nameFromState, ens: ensFromState },
showModal,
networkType,
} = this.state;

const account = {
Expand All @@ -973,6 +1037,9 @@ class DrawerView extends PureComponent {
this.currentBalance = fiatBalance;
const fiatBalanceStr = renderFiat(this.currentBalance, currentCurrency);
const accountName = isDefaultAccountName(name) && ens ? ens : name;
const checkIfCustomNetworkExists = networkOnboardedState.filter(
(item) => item.network === sanitizeUrl(switchedNetwork.networkUrl)
);

return (
<View style={styles.wrapper} testID={'drawer-screen'}>
Expand Down Expand Up @@ -1120,20 +1187,35 @@ class DrawerView extends PureComponent {
</View>
</ScrollView>
<Modal
isVisible={this.props.networkModalVisible}
onBackdropPress={this.toggleNetworksModal}
onBackButtonPress={this.toggleNetworksModal}
onSwipeComplete={this.toggleNetworksModal}
isVisible={networkModalVisible || networkOnboarding.showNetworkOnboarding}
onBackdropPress={showModal ? null : this.toggleNetworksModal}
onBackButtonPress={showModal ? null : this.toggleNetworksModa}
onSwipeComplete={showModal ? null : this.toggleNetworksModa}
swipeDirection={'down'}
propagateSwipe
backdropColor={colors.overlay.default}
backdropOpacity={1}
>
<NetworkList
navigation={this.props.navigation}
onClose={this.onNetworksModalClose}
showInvalidCustomNetworkAlert={this.showInvalidCustomNetworkAlert}
/>
{showModal ||
networkOnboarding.showNetworkOnboarding ||
(currentRoute === 'WalletView' &&
switchedNetwork.networkStatus &&
checkIfCustomNetworkExists.length === 0) ? (
<NetworkInfo
onClose={this.onInfoNetworksModalClose}
type={networkType || networkOnboarding.networkType}
ticker={ticker}
navigation={navigation}
/>
) : (
<NetworkList
navigation={this.props.navigation}
onClose={this.onNetworksModalClose}
onNetworkSelected={this.onNetworkSelected}
showInvalidCustomNetworkAlert={this.showInvalidCustomNetworkAlert}
switchModalContent={this.switchModalContent}
/>
)}
</Modal>
<Modal backdropColor={colors.overlay.default} backdropOpacity={1} isVisible={!!invalidCustomNetwork}>
<InvalidCustomNetworkAlert
Expand Down Expand Up @@ -1208,6 +1290,10 @@ const mapStateToProps = (state) => ({
collectibles: collectiblesSelector(state),
seedphraseBackedUp: state.user.seedphraseBackedUp,
currentRoute: getCurrentRoute(state),
networkOnboarding: state.networkOnboarded.networkState,
networkOnboardedState: state.networkOnboarded.networkOnboardedState,
networkProvider: state.engine.backgroundState.NetworkController.provider,
switchedNetwork: state.networkOnboarded.switchedNetwork,
});

const mapDispatchToProps = (dispatch) => ({
Expand All @@ -1218,6 +1304,8 @@ const mapDispatchToProps = (dispatch) => ({
newAssetTransaction: (selectedAsset) => dispatch(newAssetTransaction(selectedAsset)),
protectWalletModalVisible: () => dispatch(protectWalletModalVisible()),
logOut: () => dispatch(logOut()),
onboardNetworkAction: (network) => dispatch(onboardNetworkAction(network)),
networkSwitched: ({ networkUrl, networkStatus }) => dispatch(networkSwitched({ networkUrl, networkStatus })),
});

DrawerView.contextType = ThemeContext;
Expand Down
3 changes: 3 additions & 0 deletions app/components/UI/NetworkInfo/InfoDescription/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import infoDescription from './infoDescription';

export default infoDescription;
76 changes: 76 additions & 0 deletions app/components/UI/NetworkInfo/InfoDescription/infoDescription.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { memo } from 'react';
import { View, Text, Linking, StyleSheet } from 'react-native';
import { strings } from '../../../../../locales/i18n';
import { useAppThemeFromContext, mockTheme } from '../../../../util/theme';

const createStyles = (colors: {
background: { default: string };
text: { default: string };
border: { muted: string };
info: { default: string };
}) =>
StyleSheet.create({
descriptionContainer: {
marginBottom: 10,
borderBottomWidth: StyleSheet.hairlineWidth,
borderColor: colors.border.muted,
},
contentContainer: {
flexDirection: 'row',
alignItems: 'center',
marginBottom: 4,
},
numberStyle: {
marginRight: 10,
color: colors.text.default,
},
link: {
color: colors.info.default,
},
description: {
width: '94%',
color: colors.text.default,
},
});

interface DescriptionProps {
description: string;
clickableText: string | undefined;
number: number;
navigation: any;
onClose: () => void;
}

const Description = (props: DescriptionProps) => {
const { description, clickableText, number, navigation, onClose } = props;
const { colors } = useAppThemeFromContext() || mockTheme;
const styles = createStyles(colors);

const handlePress = () => {
if (number === 2) {
Linking.openURL(strings('network_information.learn_more_url'));
} else {
onClose();
navigation.push('AddAsset', { assetType: 'token' });
}
};

return (
<View style={styles.descriptionContainer}>
<View style={styles.contentContainer}>
<Text style={styles.numberStyle}>{number}.</Text>
<Text style={styles.description}>
<Text>{description}</Text>
{clickableText && (
<Text onPress={handlePress} style={styles.link}>
{' '}
{clickableText}
</Text>
)}
</Text>
</View>
</View>
);
};

export default memo(Description);
16 changes: 16 additions & 0 deletions app/components/UI/NetworkInfo/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`NetworkInfo should render correctly 1`] = `
<NetworkInfo
dispatch={[Function]}
networkProvider={
Object {
"rpcTarget": "http://10.0.2.2:8545",
"type": "mainnet",
}
}
onClose={[Function]}
ticker=""
type=""
/>
`;
41 changes: 41 additions & 0 deletions app/components/UI/NetworkInfo/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import { shallow } from 'enzyme';
import NetworkInfo from './';
import configureMockStore from 'redux-mock-store';
import { Provider } from 'react-redux';

const mockStore = configureMockStore();
const initialState = {
privacy: {
approvedHosts: {},
},
engine: {
backgroundState: {
NetworkController: {
provider: { type: 'mainnet', rpcTarget: 'http://10.0.2.2:8545' },
},
PreferencesController: { frequentRpcList: ['http://10.0.2.2:8545'] },
},
},
networkOnboarded: {
networkOnboardedState: [{ network: 'mainnet', onboarded: true }],
},
};
const store = mockStore(initialState);

describe('NetworkInfo', () => {
it('should render correctly', () => {
const wrapper = shallow(
<Provider store={store}>
<NetworkInfo
type={''}
onClose={function (): void {
throw new Error('Function not implemented.');
}}
ticker={''}
/>
</Provider>
);
expect(wrapper.dive()).toMatchSnapshot();
});
});
Loading

0 comments on commit fa63312

Please sign in to comment.