diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 8bd0f2b08..17bae2973 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -23,6 +23,7 @@ export default class AppStateController extends EventEmitter { this.store = new ObservableStore(Object.assign({ timeoutMinutes: 0, connectedStatusPopoverHasBeenShown: true, + defaultHomeActiveTabName: null, }, initState)) this.timer = null @@ -90,6 +91,16 @@ export default class AppStateController extends EventEmitter { } } + /** + * Sets the default home tab + * @param {string} [defaultHomeActiveTabName] - the tab name + */ + setDefaultHomeActiveTabName (defaultHomeActiveTabName) { + this.store.updateState({ + defaultHomeActiveTabName, + }) + } + /** * Record that the user has seen the connected status info popover */ diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 2ec987691..394ffc139 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -505,6 +505,7 @@ export default class MetamaskController extends EventEmitter { // AppStateController setLastActiveTime: nodeify(this.appStateController.setLastActiveTime, this.appStateController), + setDefaultHomeActiveTabName: nodeify(this.appStateController.setDefaultHomeActiveTabName, this.appStateController), setConnectedStatusPopoverHasBeenShown: nodeify(this.appStateController.setConnectedStatusPopoverHasBeenShown, this.appStateController), // EnsController diff --git a/ui/app/components/ui/tabs/tabs.component.js b/ui/app/components/ui/tabs/tabs.component.js index 9f27dbd2c..b3bd73fdd 100644 --- a/ui/app/components/ui/tabs/tabs.component.js +++ b/ui/app/components/ui/tabs/tabs.component.js @@ -3,24 +3,31 @@ import PropTypes from 'prop-types' export default class Tabs extends Component { static defaultProps = { - defaultActiveTabIndex: 0, + defaultActiveTabName: null, + onTabClick: null, } static propTypes = { - defaultActiveTabIndex: PropTypes.number, + defaultActiveTabName: PropTypes.string, + onTabClick: PropTypes.func, children: PropTypes.node.isRequired, } state = { - activeTabIndex: this.props.defaultActiveTabIndex, + activeTabIndex: Math.max(this._findChildByName(this.props.defaultActiveTabName), 0), } - handleTabClick (tabIndex) { + handleTabClick (tabIndex, tabName) { + const { onTabClick } = this.props const { activeTabIndex } = this.state if (tabIndex !== activeTabIndex) { this.setState({ activeTabIndex: tabIndex, + }, () => { + if (onTabClick) { + onTabClick(tabName) + } }) } } @@ -29,11 +36,11 @@ export default class Tabs extends Component { const numberOfTabs = React.Children.count(this.props.children) return React.Children.map(this.props.children, (child, index) => { + const tabName = child?.props.name return child && React.cloneElement(child, { - onClick: (index) => this.handleTabClick(index), + onClick: (index) => this.handleTabClick(index, tabName), tabIndex: index, isActive: numberOfTabs > 1 && index === this.state.activeTabIndex, - key: index, }) }) } @@ -66,4 +73,14 @@ export default class Tabs extends Component { ) } + + /** + * Returns the index of the child with the given key + * @param {string} key - the child key to search for + * @returns {number} + * @private + */ + _findChildByName (name) { + return React.Children.toArray(this.props.children).findIndex((c) => c?.props.name === name) + } } diff --git a/ui/app/components/ui/tabs/tabs.stories.js b/ui/app/components/ui/tabs/tabs.stories.js index 32699d07b..0e2caffed 100644 --- a/ui/app/components/ui/tabs/tabs.stories.js +++ b/ui/app/components/ui/tabs/tabs.stories.js @@ -1,7 +1,7 @@ import React from 'react' import Tab from './tab/tab.component' import Tabs from './tabs.component' -import { number, text } from '@storybook/addon-knobs/react' +import { text } from '@storybook/addon-knobs/react' export default { title: 'Tabs', @@ -20,9 +20,7 @@ function renderTab (id) { export const twoTabs = () => { return ( - + { ['A', 'B'] .map(renderTab) @@ -33,9 +31,7 @@ export const twoTabs = () => { export const manyTabs = () => { return ( - + { ['A', 'B', 'C', 'D', 'E'] .map(renderTab) diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index 998593fb3..4c423d350 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -56,6 +56,8 @@ export default class Home extends PureComponent { decimals: PropTypes.number, symbol: PropTypes.string, }), + defaultHomeActiveTabName: PropTypes.string.isRequired, + onTabClick: PropTypes.func.isRequired, } UNSAFE_componentWillMount () { @@ -209,6 +211,8 @@ export default class Home extends PureComponent { render () { const { + defaultHomeActiveTabName, + onTabClick, forgottenPassword, history, connectedStatusPopoverHasBeenShown, @@ -257,7 +261,7 @@ export default class Home extends PureComponent {
{ homeOverview }
- + { showRestorePrompt, selectedAddress, connectedStatusPopoverHasBeenShown, + defaultHomeActiveTabName, } = metamask const accountBalance = getCurrentEthBalance(state) const { forgottenPassword, threeBoxLastUpdated } = appState @@ -63,6 +65,7 @@ const mapStateToProps = (state) => { firstPermissionsRequestId, totalUnapprovedCount, connectedStatusPopoverHasBeenShown, + defaultHomeActiveTabName, } } @@ -82,6 +85,7 @@ const mapDispatchToProps = (dispatch) => ({ restoreFromThreeBox: (address) => dispatch(restoreFromThreeBox(address)), setShowRestorePromptToFalse: () => dispatch(setShowRestorePromptToFalse()), setConnectedStatusPopoverHasBeenShown: () => dispatch(setConnectedStatusPopoverHasBeenShown()), + onTabClick: (name) => dispatch(setDefaultHomeActiveTabName(name)), }) export default compose( diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 10c9a937d..e61e1bb31 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -1815,6 +1815,12 @@ export function updatePreferences (value) { } } +export function setDefaultHomeActiveTabName (value) { + return async () => { + await promisifiedBackground.setDefaultHomeActiveTabName(value) + } +} + export function setUseNativeCurrencyAsPrimaryCurrencyPreference (value) { return setPreference('useNativeCurrencyAsPrimaryCurrency', value) }