mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Added the ability to navigate multiple SIWE notifications (#18103)
This commit is contained in:
parent
2e856894cc
commit
f3147bcfb7
@ -5,6 +5,76 @@ exports[`SignatureRequestSIWE (Sign in with Ethereum) should match snapshot 1`]
|
||||
<div
|
||||
class="signature-request-siwe"
|
||||
>
|
||||
<div
|
||||
class="request-signature__navigation"
|
||||
>
|
||||
<div
|
||||
class="confirm-page-container-navigation"
|
||||
style="display: none;"
|
||||
>
|
||||
<div
|
||||
class="confirm-page-container-navigation__container"
|
||||
data-testid="navigation-container"
|
||||
style="visibility: hidden;"
|
||||
>
|
||||
<button
|
||||
class="confirm-page-container-navigation__arrow"
|
||||
data-testid="first-page"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-double-left fa-2x"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="confirm-page-container-navigation__arrow"
|
||||
data-testid="previous-page"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-left fa-2x"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="confirm-page-container-navigation__textcontainer"
|
||||
>
|
||||
<div
|
||||
class="confirm-page-container-navigation__navtext"
|
||||
>
|
||||
0
|
||||
|
||||
of
|
||||
|
||||
1
|
||||
</div>
|
||||
<div
|
||||
class="confirm-page-container-navigation__longtext"
|
||||
>
|
||||
requests waiting to be acknowledged
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="confirm-page-container-navigation__container"
|
||||
style="visibility: initial;"
|
||||
>
|
||||
<button
|
||||
class="confirm-page-container-navigation__arrow"
|
||||
data-testid="next-page"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-right fa-2x"
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
class="confirm-page-container-navigation__arrow"
|
||||
data-testid="last-page"
|
||||
>
|
||||
<i
|
||||
class="fa fa-angle-double-right fa-2x"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box network-account-balance-header box--padding-4 box--display-flex box--flex-direction-row box--justify-content-space-between box--align-items-center"
|
||||
>
|
||||
|
@ -1,20 +1,25 @@
|
||||
import React, { useCallback, useContext, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import log from 'loglevel';
|
||||
import { isValidSIWEOrigin } from '@metamask/controller-utils';
|
||||
import { BannerAlert, Text } from '../../component-library';
|
||||
import Popover from '../../ui/popover';
|
||||
import Checkbox from '../../ui/check-box';
|
||||
import Button from '../../ui/button';
|
||||
import { I18nContext } from '../../../contexts/i18n';
|
||||
import { PageContainerFooter } from '../../ui/page-container';
|
||||
import { isAddressLedger } from '../../../ducks/metamask/metamask';
|
||||
import {
|
||||
accountsWithSendEtherInfoSelector,
|
||||
getSubjectMetadata,
|
||||
getTotalUnapprovedMessagesCount,
|
||||
unconfirmedMessagesHashSelector,
|
||||
} from '../../../selectors';
|
||||
import { getAccountByAddress } from '../../../helpers/utils/util';
|
||||
import { getAccountByAddress, valuesFor } from '../../../helpers/utils/util';
|
||||
import { formatMessageParams } from '../../../../shared/modules/siwe';
|
||||
import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck';
|
||||
|
||||
import {
|
||||
SEVERITIES,
|
||||
@ -23,6 +28,9 @@ import {
|
||||
|
||||
import SecurityProviderBannerMessage from '../security-provider-banner-message/security-provider-banner-message';
|
||||
import { SECURITY_PROVIDER_MESSAGE_SEVERITIES } from '../security-provider-banner-message/security-provider-banner-message.constants';
|
||||
import ConfirmPageContainerNavigation from '../confirm-page-container/confirm-page-container-navigation';
|
||||
import { getMostRecentOverviewPage } from '../../../ducks/history/history';
|
||||
import { showModal, cancelMsgs } from '../../../store/actions';
|
||||
import LedgerInstructionField from '../ledger-instruction-field';
|
||||
|
||||
import SignatureRequestHeader from '../signature-request-header';
|
||||
@ -34,11 +42,17 @@ export default function SignatureRequestSIWE({
|
||||
cancelPersonalMessage,
|
||||
signPersonalMessage,
|
||||
}) {
|
||||
const dispatch = useDispatch();
|
||||
const history = useHistory();
|
||||
const t = useContext(I18nContext);
|
||||
|
||||
const allAccounts = useSelector(accountsWithSendEtherInfoSelector);
|
||||
const subjectMetadata = useSelector(getSubjectMetadata);
|
||||
|
||||
const messagesCount = useSelector(getTotalUnapprovedMessagesCount);
|
||||
const messagesList = useSelector(unconfirmedMessagesHashSelector);
|
||||
const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage);
|
||||
|
||||
const {
|
||||
msgParams: {
|
||||
from,
|
||||
@ -90,8 +104,29 @@ export default function SignatureRequestSIWE({
|
||||
[cancelPersonalMessage],
|
||||
);
|
||||
|
||||
const handleCancelAll = () => {
|
||||
const unapprovedTxCount = messagesCount;
|
||||
|
||||
dispatch(
|
||||
showModal({
|
||||
name: 'REJECT_TRANSACTIONS',
|
||||
unapprovedTxCount,
|
||||
onSubmit: async () => {
|
||||
await dispatch(cancelMsgs(valuesFor(messagesList)));
|
||||
dispatch(clearConfirmTransaction());
|
||||
history.push(mostRecentOverviewPage);
|
||||
},
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const rejectNText = t('rejectRequestsN', [messagesCount]);
|
||||
|
||||
return (
|
||||
<div className="signature-request-siwe">
|
||||
<div className="request-signature__navigation">
|
||||
<ConfirmPageContainerNavigation />
|
||||
</div>
|
||||
<SignatureRequestHeader txData={txData} />
|
||||
<Header
|
||||
fromAccount={fromAccount}
|
||||
@ -150,6 +185,18 @@ export default function SignatureRequestSIWE({
|
||||
submitText={t('signin')}
|
||||
submitButtonType={isSIWEDomainValid ? 'primary' : 'danger-primary'}
|
||||
/>
|
||||
{messagesCount > 1 ? (
|
||||
<Button
|
||||
type="link"
|
||||
className="request-signature__container__reject"
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
handleCancelAll();
|
||||
}}
|
||||
>
|
||||
{rejectNText}
|
||||
</Button>
|
||||
) : null}
|
||||
{isShowingDomainWarning && (
|
||||
<Popover
|
||||
onClose={() => setIsShowingDomainWarning(false)}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import { MESSAGE_TYPE } from '../../../../shared/constants/app';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
@ -21,6 +22,14 @@ const mockStoreInitialState = {
|
||||
},
|
||||
};
|
||||
|
||||
const mockShowModal = jest.fn();
|
||||
|
||||
jest.mock('../../../store/actions.ts', () => {
|
||||
return {
|
||||
showModal: () => mockShowModal,
|
||||
};
|
||||
});
|
||||
|
||||
const mockProps = {
|
||||
cancelPersonalMessage: jest.fn(),
|
||||
signPersonalMessage: jest.fn(),
|
||||
@ -136,4 +145,84 @@ describe('SignatureRequestSIWE (Sign in with Ethereum)', () => {
|
||||
container.querySelector('.mock-ledger-instruction-field'),
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('when there is only one unconfirmed tx', () => {
|
||||
it('should not show multiple notifications header', () => {
|
||||
const store = configureStore(mockStoreInitialState);
|
||||
const txData = cloneDeep(mockProps.txData);
|
||||
|
||||
const { container } = renderWithProvider(
|
||||
<SignatureRequestSIWE {...mockProps} txData={txData} />,
|
||||
store,
|
||||
);
|
||||
|
||||
expect(
|
||||
container.querySelector('.confirm-page-container-navigation'),
|
||||
).toHaveStyle('display: none');
|
||||
});
|
||||
|
||||
it('should not show Reject request button', () => {
|
||||
const { container } = render();
|
||||
expect(
|
||||
container.querySelector('.request-signature__container__reject'),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there is more than one unconfirmed tx', () => {
|
||||
let renderResult;
|
||||
|
||||
beforeEach(() => {
|
||||
const store = configureStore({
|
||||
...mockStoreInitialState,
|
||||
metamask: {
|
||||
...mockStoreInitialState.metamask,
|
||||
unapprovedTxs: {
|
||||
...mockStoreInitialState.metamask.unapprovedTxs,
|
||||
'0x12333': {
|
||||
chainId: mockStoreInitialState.metamask.providerConfig.chainId,
|
||||
},
|
||||
},
|
||||
unapprovedMsgCount: 2,
|
||||
},
|
||||
});
|
||||
|
||||
const txData = cloneDeep(mockProps.txData);
|
||||
renderResult = renderWithProvider(
|
||||
<SignatureRequestSIWE {...mockProps} txData={txData} />,
|
||||
store,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
renderResult = null;
|
||||
});
|
||||
|
||||
it('should show multiple notifications header', () => {
|
||||
const { container } = renderResult;
|
||||
expect(
|
||||
container.getElementsByClassName('signature-request-siwe-header'),
|
||||
).toHaveLength(1);
|
||||
|
||||
expect(
|
||||
container.querySelector('.confirm-page-container-navigation'),
|
||||
).toHaveStyle('display: flex');
|
||||
});
|
||||
|
||||
it('should show Reject request button', () => {
|
||||
const { getByText } = renderResult;
|
||||
const cancelAll = getByText('Reject 2 requests');
|
||||
|
||||
expect(cancelAll).toHaveClass('request-signature__container__reject');
|
||||
expect(cancelAll).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should show cancel all modal on Reject request button click', () => {
|
||||
const { getByText } = renderResult;
|
||||
const cancelAll = getByText('Reject 2 requests');
|
||||
|
||||
fireEvent.click(cancelAll);
|
||||
expect(mockShowModal).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -61,7 +61,7 @@ const mockStoreWithEth = {
|
||||
cachedBalances: {},
|
||||
unapprovedDecryptMsgs: {},
|
||||
unapprovedEncryptionPublicKeyMsgs: {},
|
||||
uncofirmedTransactions: {},
|
||||
unconfirmedTransactions: {},
|
||||
selectedAddress: '0xd8f6a2ffb0fc5952d16c9768b71cfd35b6399aa5',
|
||||
nativeCurrency: 'ETH',
|
||||
currentCurrency: 'usd',
|
||||
|
Loading…
Reference in New Issue
Block a user