1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 11:22:43 +02:00

[FLASK] Revert changes made to stable permission display (UI design) (#18470)

* Revert changes made to stable permission display (UI design)

* Add test for new component

* Update paddings for install flow

* Fix missing icons on snap installation flow

* Update storybook path

* Add targetSubjectMetadata param

---------

Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>
Co-authored-by: Frederik Bolding <frederik.bolding@gmail.com>
This commit is contained in:
David Drazic 2023-04-14 12:04:23 +02:00 committed by GitHub
parent 17147b3817
commit 3eefe874a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 205 additions and 48 deletions

View File

@ -0,0 +1 @@
export { default } from './snap-permissions-list';

View File

@ -0,0 +1,37 @@
import React from 'react';
import PropTypes from 'prop-types';
import { getWeightedPermissions } from '../../../../helpers/utils/permission';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import PermissionCell from '../../permission-cell';
import Box from '../../../ui/box';
export default function SnapPermissionsList({
permissions,
targetSubjectMetadata,
}) {
const t = useI18nContext();
return (
<Box paddingTop={2} paddingBottom={2} className="snap-permissions-list">
{getWeightedPermissions(t, permissions, targetSubjectMetadata).map(
(permission, index) => {
return (
<PermissionCell
title={permission.label}
description={permission.description}
weight={permission.weight}
avatarIcon={permission.leftIcon}
dateApproved={permission?.permissionValue?.date}
key={`${permission.permissionName}-${index}`}
/>
);
},
)}
</Box>
);
}
SnapPermissionsList.propTypes = {
permissions: PropTypes.object.isRequired,
targetSubjectMetadata: PropTypes.object.isRequired,
};

View File

@ -0,0 +1,37 @@
import React from 'react';
import SnapPermissionsList from '.';
export default {
title: 'Components/App/flask/SnapPermissionsList',
component: SnapPermissionsList,
argTypes: {
permissions: {
control: 'object',
},
},
};
export const DefaultStory = (args) => <SnapPermissionsList {...args} />;
DefaultStory.storyName = 'Default';
DefaultStory.args = {
permissions: {
eth_accounts: {},
snap_dialog: {},
snap_getBip32PublicKey: {
caveats: [
{
value: [
{
path: ['m', `44'`, `0'`],
curve: 'secp256k1',
},
],
},
],
},
},
};

View File

@ -0,0 +1,37 @@
import React from 'react';
import { screen } from '@testing-library/react';
import { renderWithProvider } from '../../../../../test/jest';
import SnapPermissionsList from './snap-permissions-list';
describe('Snap Permission List', () => {
const mockPermissionData = {
snap_dialog: {
caveats: null,
date: 1680709920602,
id: '4dduR1BpsmS0ZJfeVtiAh',
invoker: 'local:http://localhost:8080',
parentCapability: 'snap_dialog',
},
};
const mockTargetSubjectMetadata = {
extensionId: null,
iconUrl: null,
name: 'TypeScript Example Snap',
origin: 'local:http://localhost:8080',
subjectType: 'snap',
version: '0.2.2',
};
it('renders permissions list for snaps', () => {
renderWithProvider(
<SnapPermissionsList
permissions={mockPermissionData}
targetSubjectMetadata={mockTargetSubjectMetadata}
/>,
);
expect(
screen.getByText('Display dialog windows in MetaMask.'),
).toBeInTheDocument();
expect(screen.getByText('Approved on 2023-04-05')).toBeInTheDocument();
});
});

View File

@ -53,6 +53,11 @@ const PermissionCell = ({
iconBackgroundColor = Color.backgroundAlternative;
}
let permissionIcon = avatarIcon;
if (typeof avatarIcon !== 'string' && avatarIcon?.props?.iconName) {
permissionIcon = avatarIcon.props.iconName;
}
return (
<Box
className="permission-cell"
@ -64,9 +69,9 @@ const PermissionCell = ({
paddingBottom={2}
>
<Box>
{typeof avatarIcon === 'string' ? (
{typeof permissionIcon === 'string' ? (
<AvatarIcon
iconName={avatarIcon}
iconName={permissionIcon}
size={ICON_SIZES.MD}
iconProps={{
size: ICON_SIZES.SM,
@ -75,7 +80,7 @@ const PermissionCell = ({
backgroundColor={iconBackgroundColor}
/>
) : (
avatarIcon
permissionIcon
)}
</Box>
<Box width="full" marginLeft={4} marginRight={4}>

View File

@ -28,11 +28,14 @@ export default class PermissionPageContainerContent extends PureComponent {
};
renderRequestedPermissions() {
const { selectedPermissions } = this.props;
const { selectedPermissions, subjectMetadata } = this.props;
return (
<div className="permission-approval-container__content__requested">
<PermissionsConnectPermissionList permissions={selectedPermissions} />
<PermissionsConnectPermissionList
permissions={selectedPermissions}
targetSubjectMetadata={subjectMetadata}
/>
</div>
);
}

View File

@ -1,9 +1,29 @@
import React from 'react';
import PropTypes from 'prop-types';
import { getWeightedPermissions } from '../../../helpers/utils/permission';
import {
getRightIcon,
getWeightedPermissions,
} from '../../../helpers/utils/permission';
import { useI18nContext } from '../../../hooks/useI18nContext';
import PermissionCell from '../permission-cell';
import Box from '../../ui/box';
/**
* Get one or more permission descriptions for a permission name.
*
* @param permission - The permission to render.
* @param index - The index of the permission.
* @returns {JSX.Element} A permission description node.
*/
function getDescriptionNode(permission, index) {
const { label, leftIcon, permissionName } = permission;
return (
<div className="permission" key={`${permissionName}-${index}`}>
{typeof leftIcon === 'string' ? <i className={leftIcon} /> : leftIcon}
{label}
{getRightIcon(permission)}
</div>
);
}
export default function PermissionsConnectPermissionList({
permissions,
@ -12,22 +32,11 @@ export default function PermissionsConnectPermissionList({
const t = useI18nContext();
return (
<Box paddingTop={2} paddingBottom={2}>
<div className="permissions-connect-permission-list">
{getWeightedPermissions(t, permissions, targetSubjectMetadata).map(
(permission, index) => {
return (
<PermissionCell
title={permission.label}
description={permission.description}
weight={permission.weight}
avatarIcon={permission.leftIcon}
dateApproved={permission?.permissionValue?.date}
key={`${permission.permissionName}-${index}`}
/>
);
},
getDescriptionNode,
)}
</Box>
</div>
);
}

View File

@ -20,18 +20,5 @@ DefaultStory.storyName = 'Default';
DefaultStory.args = {
permissions: {
eth_accounts: {},
snap_dialog: {},
snap_getBip32PublicKey: {
caveats: [
{
value: [
{
path: ['m', `44'`, `0'`],
curve: 'secp256k1',
},
],
},
],
},
},
};

View File

@ -15,13 +15,23 @@ import {
} from '../../../shared/constants/permissions';
import Tooltip from '../../components/ui/tooltip';
import {
AvatarIcon,
///: BEGIN:ONLY_INCLUDE_IN(flask)
Text,
Icon,
///: END:ONLY_INCLUDE_IN
} from '../../components/component-library';
import { ICON_NAMES } from '../../components/component-library/icon/deprecated';
import {
ICON_NAMES,
ICON_SIZES,
} from '../../components/component-library/icon/deprecated';
///: BEGIN:ONLY_INCLUDE_IN(flask)
import { Color, FONT_WEIGHT, TextVariant } from '../constants/design-system';
import {
Color,
FONT_WEIGHT,
IconColor,
TextVariant,
} from '../constants/design-system';
import {
coinTypeToProtocolName,
getSnapDerivationPathName,
@ -31,10 +41,33 @@ import {
const UNKNOWN_PERMISSION = Symbol('unknown');
///: BEGIN:ONLY_INCLUDE_IN(flask)
const RIGHT_INFO_ICON = (
<Icon
name={ICON_NAMES.INFO}
size={ICON_SIZES.SM}
color={IconColor.iconMuted}
/>
);
///: END:ONLY_INCLUDE_IN
function getLeftIcon(iconName) {
return (
<AvatarIcon
iconName={iconName}
size={ICON_SIZES.SM}
iconProps={{
size: ICON_SIZES.XS,
}}
/>
);
}
export const PERMISSION_DESCRIPTIONS = deepFreeze({
[RestrictedMethods.eth_accounts]: ({ t }) => ({
label: t('permission_ethereumAccounts'),
leftIcon: ICON_NAMES.EYE,
leftIcon: getLeftIcon(ICON_NAMES.EYE),
rightIcon: null,
weight: 2,
}),
///: BEGIN:ONLY_INCLUDE_IN(flask)
@ -251,7 +284,8 @@ export const PERMISSION_DESCRIPTIONS = deepFreeze({
[RestrictedMethods.wallet_snap]: ({ t, permissionValue }) => {
const snaps = permissionValue.caveats[0].value;
const baseDescription = {
leftIcon: ICON_NAMES.FLASH,
leftIcon: getLeftIcon(ICON_NAMES.FLASH),
rightIcon: RIGHT_INFO_ICON,
};
return Object.keys(snaps).map((snapId) => {
@ -373,7 +407,8 @@ export const PERMISSION_DESCRIPTIONS = deepFreeze({
///: END:ONLY_INCLUDE_IN
[UNKNOWN_PERMISSION]: ({ t, permissionName }) => ({
label: t('permission_unknown', [permissionName ?? 'undefined']),
leftIcon: ICON_NAMES.QUESTION,
leftIcon: getLeftIcon(ICON_NAMES.QUESTION),
rightIcon: null,
weight: 4,
}),
});

View File

@ -1,7 +1,6 @@
import PropTypes from 'prop-types';
import React, { useCallback, useState } from 'react';
import { PageContainerFooter } from '../../../../components/ui/page-container';
import PermissionsConnectPermissionList from '../../../../components/app/permissions-connect-permission-list';
import { useI18nContext } from '../../../../hooks/useI18nContext';
import SnapInstallWarning from '../../../../components/app/flask/snap-install-warning';
import Box from '../../../../components/ui/box/box';
@ -21,6 +20,7 @@ import SnapAuthorship from '../../../../components/app/flask/snap-authorship';
import { Text } from '../../../../components/component-library';
import { useOriginMetadata } from '../../../../hooks/useOriginMetadata';
import { getSnapName } from '../../../../helpers/utils/util';
import SnapPermissionsList from '../../../../components/app/flask/snap-permissions-list';
export default function SnapInstall({
request,
@ -87,12 +87,16 @@ export default function SnapInstall({
className="headers"
alignItems={AlignItems.center}
flexDirection={FLEX_DIRECTION.COLUMN}
paddingLeft={4}
paddingRight={4}
>
<SnapAuthorship snapId={targetSubjectMetadata.origin} />
<Box paddingLeft={4} paddingRight={4}>
<SnapAuthorship snapId={targetSubjectMetadata.origin} />
</Box>
{!hasError && (
<Text padding={[4, 4, 0, 4]} variant={TextVariant.headingLg}>
<Text
variant={TextVariant.headingLg}
paddingTop={4}
paddingBottom={2}
>
{t('snapInstall')}
</Text>
)}
@ -114,6 +118,8 @@ export default function SnapInstall({
<Text
className="headers__permission-description"
paddingBottom={4}
paddingLeft={4}
paddingRight={4}
textAlign={TEXT_ALIGN.CENTER}
>
{t('snapInstallRequestsPermission', [
@ -121,7 +127,7 @@ export default function SnapInstall({
<b key="2">{snapName}</b>,
])}
</Text>
<PermissionsConnectPermissionList
<SnapPermissionsList
permissions={requestState.permissions || {}}
targetSubjectMetadata={targetSubjectMetadata}
/>

View File

@ -19,7 +19,6 @@ import SnapAuthorship from '../../../../components/app/flask/snap-authorship';
import Box from '../../../../components/ui/box';
import SnapRemoveWarning from '../../../../components/app/flask/snap-remove-warning';
import ToggleButton from '../../../../components/ui/toggle-button';
import PermissionsConnectPermissionList from '../../../../components/app/permissions-connect-permission-list/permissions-connect-permission-list';
import ConnectedSitesList from '../../../../components/app/connected-sites-list';
import Tooltip from '../../../../components/ui/tooltip';
import { SNAPS_LIST_ROUTE } from '../../../../helpers/constants/routes';
@ -38,6 +37,7 @@ import {
getTargetSubjectMetadata,
} from '../../../../selectors';
import { formatDate } from '../../../../helpers/utils/util';
import SnapPermissionsList from '../../../../components/app/flask/snap-permissions-list';
function ViewSnap() {
const t = useI18nContext();
@ -182,7 +182,7 @@ function ViewSnap() {
{t('snapAccess', [snap.manifest.proposedName])}
</Typography>
<Box width={BLOCK_SIZES.FULL}>
<PermissionsConnectPermissionList
<SnapPermissionsList
permissions={permissions ?? {}}
targetSubjectMetadata={targetSubjectMetadata}
/>