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

feat: adding / deleting additional RPC URLs #25452

Merged
merged 16 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think ={true} is required here; I think the presence of the attribute infers 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}
Copy link
Contributor

Choose a reason for hiding this comment

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

same here you can just use danger

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,
Copy link
Contributor

Choose a reason for hiding this comment

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

do we need to specify the value of children to undefined here? doesn't this take undefined by default ?

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 got a type error without it

Screenshot 2024-06-25 at 8 18 38 AM

variant: TextVariant.bodySmMedium,
}}
/>

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

Choose a reason for hiding this comment

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

if we decide to include input validation here, it would be a good idea to write unit tests for this modal with the different scenarios ( rpcUrl doesn't match with chainID, rpcURL already added ...etc )

);
};

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