Skip to content

Commit

Permalink
feat: adding / deleting additional RPC URLs (#25452)
Browse files Browse the repository at this point in the history
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Initial UI for adding and deleting multiple RPC URLs. The add and delete
buttons don't do anything yet. Just UI until the network controller gets
upgraded.

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/25452?quickstart=1)

## **Related issues**


## **Manual testing steps**

1. Build with ENABLE_NETWORK_UI_REDESIGN=1 yarn start
2. Open networks, right click edit one
3. Click RPC dropdown
4. Add and delete RPC endpoints



## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**



https://github.com/MetaMask/metamask-extension/assets/3500406/42047230-b258-4c1b-a37e-fb3c0f300913



## **Pre-merge author checklist**

- [ ] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: David Walsh <davidwalsh83@gmail.com>
Co-authored-by: salimtb <salim.toubal@outlook.com>
  • Loading branch information
3 people authored Jun 28, 2024
1 parent fdc898e commit 1f74b08
Show file tree
Hide file tree
Showing 17 changed files with 294 additions and 59 deletions.
15 changes: 15 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import {
BlockSize,
Display,
} from '../../../../helpers/constants/design-system';
import {
Box,
ButtonPrimary,
ButtonPrimarySize,
ButtonSecondary,
ButtonSecondarySize,
Modal,
ModalBody,
ModalContent,
ModalHeader,
ModalOverlay,
} from '../../../component-library';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import {
hideModal,
setEditedNetwork,
toggleNetworkMenu,
} from '../../../../store/actions';

const ConfirmDeleteRpcUrlModal = () => {
const t = useI18nContext();
const dispatch = useDispatch();
return (
<Modal
isClosedOnEscapeKey={true}
isClosedOnOutsideClick={true}
isOpen={true}
onClose={() => {
dispatch(setEditedNetwork());
dispatch(hideModal());
}}
>
<ModalOverlay />
<ModalContent>
<ModalHeader>{t('confirmDeletion')}</ModalHeader>
<ModalBody>
<Box>{t('confirmRpcUrlDeletionMessage')}</Box>
<Box display={Display.Flex} gap={4} marginTop={6}>
<ButtonSecondary
width={BlockSize.Full}
size={ButtonSecondarySize.Lg}
onClick={() => {
dispatch(hideModal());
dispatch(toggleNetworkMenu());
}}
>
{t('back')}
</ButtonSecondary>
<ButtonPrimary
width={BlockSize.Full}
size={ButtonPrimarySize.Lg}
danger={true}
onClick={() => {
console.log('TODO: Delete RPc URL');
}}
>
{t('deleteRpcUrl')}
</ButtonPrimary>
</Box>
</ModalBody>
</ModalContent>
</Modal>
);
};

export default ConfirmDeleteRpcUrlModal;
14 changes: 14 additions & 0 deletions ui/components/app/modals/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import TransactionAlreadyConfirmed from './transaction-already-confirmed';
// Metamask Notifications
import ConfirmTurnOffProfileSyncing from './confirm-turn-off-profile-syncing';
import TurnOnMetamaskNotifications from './turn-on-metamask-notifications/turn-on-metamask-notifications';
import ConfirmDeleteRpcUrlModal from './confirm-delete-rpc-url-modal/confirm-delete-rpc-url-modal';

const modalContainerBaseStyle = {
transform: 'translate3d(-50%, 0, 0px)',
Expand Down Expand Up @@ -230,6 +231,19 @@ const MODALS = {
},
},

CONFIRM_DELETE_RPC_URL: {
contents: <ConfirmDeleteRpcUrlModal />,
mobileModalStyle: {
...modalContainerMobileStyle,
},
laptopModalStyle: {
...modalContainerLaptopStyle,
},
contentStyle: {
borderRadius: '8px',
},
},

EDIT_APPROVAL_PERMISSION: {
contents: <EditApprovalPermission />,
mobileModalStyle: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import {
Box,
ButtonPrimary,
ButtonPrimarySize,
FormTextField,
} from '../../../component-library';
import {
BlockSize,
Display,
TextVariant,
} from '../../../../helpers/constants/design-system';
import { useI18nContext } from '../../../../hooks/useI18nContext';

const AddRpcUrlModal = () => {
const t = useI18nContext();

return (
<Box padding={4}>
<FormTextField
id="additional-rpc-url"
label={t('additionalRpcUrl')}
labelProps={{
children: undefined,
variant: TextVariant.bodySmMedium,
}}
/>

<ButtonPrimary
size={ButtonPrimarySize.Lg}
display={Display.Block}
width={BlockSize.Full}
marginTop={8}
marginLeft={'auto'}
marginRight={'auto'}
>
{t('addUrl')}
</ButtonPrimary>
</Box>
);
};

export default AddRpcUrlModal;
80 changes: 56 additions & 24 deletions ui/components/multichain/network-list-menu/network-list-menu.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useEffect, useState } from 'react';
import React, { useContext, useEffect, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import { useDispatch, useSelector } from 'react-redux';
Expand All @@ -15,6 +15,7 @@ import {
toggleNetworkMenu,
updateNetworksList,
setNetworkClientIdForDomain,
setEditedNetwork,
} from '../../../store/actions';
import {
FEATURED_RPCS,
Expand All @@ -32,6 +33,7 @@ import {
getOriginOfCurrentTab,
getUseRequestQueue,
getNetworkConfigurations,
getEditedNetwork,
} from '../../../selectors';
import ToggleButton from '../../ui/toggle-button';
import {
Expand Down Expand Up @@ -70,6 +72,7 @@ import { getLocalNetworkMenuRedesignFeatureFlag } from '../../../helpers/utils/f
import AddNetworkModal from '../../../pages/onboarding-flow/add-network-modal';
import PopularNetworkList from './popular-network-list/popular-network-list';
import NetworkListSearch from './network-list-search/network-list-search';
import AddRpcUrlModal from './add-rpc-url-modal/add-rpc-url-modal';

const ACTION_MODES = {
// Displays the search box and network list
Expand All @@ -78,14 +81,13 @@ const ACTION_MODES = {
ADD: 'add',
// Displays the Edit form
EDIT: 'edit',
// Displays the page for adding an additional RPC URL
ADD_RPC: 'add_rpc',
};

export const NetworkListMenu = ({ onClose }) => {
const t = useI18nContext();

const [actionMode, setActionMode] = useState(ACTION_MODES.LIST);
const [modalTitle, setModalTitle] = useState(t('networkMenuHeading'));
const [networkToEdit, setNetworkToEdit] = useState(null);
const nonTestNetworks = useSelector(getNonTestNetworks);
const testNetworks = useSelector(getTestNetworks);
const showTestNetworks = useSelector(getShowTestNetworks);
Expand Down Expand Up @@ -114,6 +116,19 @@ export const NetworkListMenu = ({ onClose }) => {

const orderedNetworksList = useSelector(getOrderedNetworksList);

const editedNetwork = useSelector(getEditedNetwork);

const [actionMode, setActionMode] = useState(
editedNetwork ? ACTION_MODES.EDIT : ACTION_MODES.LIST,
);

const networkToEdit = useMemo(() => {
const network = [...nonTestNetworks, ...testNetworks].find(
(n) => n.id === editedNetwork?.networkConfigurationId,
);
return network ? { ...network, label: network.nickname } : undefined;
}, [editedNetwork, nonTestNetworks, testNetworks]);

const networkConfigurationChainIds = Object.values(networkConfigurations).map(
(net) => net.chainId,
);
Expand Down Expand Up @@ -259,12 +274,12 @@ export const NetworkListMenu = ({ onClose }) => {

const getOnEditCallback = (network) => {
return () => {
const networkToUse = {
...network,
label: network.nickname,
};
setModalTitle(network.nickname);
setNetworkToEdit(networkToUse);
dispatch(
setEditedNetwork({
networkConfigurationId: network.id,
nickname: network.nickname,
}),
);
setActionMode(ACTION_MODES.EDIT);
};
};
Expand Down Expand Up @@ -518,7 +533,6 @@ export const NetworkListMenu = ({ onClose }) => {
category: MetaMetricsEventCategory.Network,
});
setActionMode(ACTION_MODES.ADD);
setModalTitle(t('addCustomNetwork'));
}}
>
{t('addNetwork')}
Expand All @@ -528,20 +542,38 @@ export const NetworkListMenu = ({ onClose }) => {
);
} else if (actionMode === ACTION_MODES.ADD) {
return <AddNetworkModal isNewNetworkFlow addNewNetwork />;
} else if (actionMode === ACTION_MODES.EDIT) {
return (
<AddNetworkModal
isNewNetworkFlow
addNewNetwork={false}
networkToEdit={networkToEdit}
onRpcUrlAdd={() => setActionMode(ACTION_MODES.ADD_RPC)}
/>
);
} else if (actionMode === ACTION_MODES.ADD_RPC) {
return <AddRpcUrlModal />;
}
return (
<AddNetworkModal
isNewNetworkFlow
addNewNetwork={actionMode === ACTION_MODES.ADD}
networkToEdit={networkToEdit}
/>
);
return null; // Unreachable, but satisfies linter
};

const headerAdditionalProps =
actionMode === ACTION_MODES.LIST
? {}
: { onBack: () => setActionMode(ACTION_MODES.LIST) };
// Modal back button
let onBack;
if (actionMode === ACTION_MODES.EDIT || actionMode === ACTION_MODES.ADD) {
onBack = () => setActionMode(ACTION_MODES.LIST);
} else if (actionMode === ACTION_MODES.ADD_RPC) {
onBack = () => setActionMode(ACTION_MODES.EDIT);
}

// Modal title
let title;
if (actionMode === ACTION_MODES.LIST) {
title = t('networkMenuHeading');
} else if (actionMode === ACTION_MODES.ADD) {
title = t('addCustomNetwork');
} else {
title = editedNetwork.nickname;
}

return (
<Modal isOpen onClose={onClose}>
Expand All @@ -560,9 +592,9 @@ export const NetworkListMenu = ({ onClose }) => {
paddingRight={4}
paddingBottom={6}
onClose={onClose}
{...headerAdditionalProps}
onBack={onBack}
>
{modalTitle}
{title}
</ModalHeader>
{renderListNetworks()}
</ModalContent>
Expand Down
13 changes: 9 additions & 4 deletions ui/ducks/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,13 @@ type AppState = {
newNftAddedMessage: string;
removeNftMessage: string;
newNetworkAddedName: string;
editedNetwork: string;
editedNetwork:
| {
networkConfigurationId: string;
nickname: string;
editCompleted: boolean;
}
| undefined;
newNetworkAddedConfigurationId: string;
selectedNetworkConfigurationId: string;
sendInputCurrencySwitched: boolean;
Expand Down Expand Up @@ -163,7 +169,7 @@ const initialState: AppState = {
newNftAddedMessage: '',
removeNftMessage: '',
newNetworkAddedName: '',
editedNetwork: '',
editedNetwork: undefined,
newNetworkAddedConfigurationId: '',
selectedNetworkConfigurationId: '',
sendInputCurrencySwitched: false,
Expand Down Expand Up @@ -489,10 +495,9 @@ export default function reduceApp(
};
}
case actionConstants.SET_EDIT_NETWORK: {
const { nickname } = action.payload;
return {
...appState,
editedNetwork: nickname,
editedNetwork: action.payload,
};
}
case actionConstants.SET_NEW_TOKENS_IMPORTED:
Expand Down
Loading

0 comments on commit 1f74b08

Please sign in to comment.