mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
[FLASK] Update snap authorship component (#18262)
* Create new snap authorship component * Add icons and fix overflow issues * Add empty state + more fixes * Fix overflow * Move some code to SnapAvatar * Fix lint * Change component name * Delete forgotten file
This commit is contained in:
parent
79b2deb194
commit
4179ce634c
@ -34,7 +34,6 @@
|
||||
@import 'edit-gas-fee-popover/network-statistics/status-slider/index';
|
||||
@import 'edit-gas-fee-popover/edit-gas-tooltip/index';
|
||||
@import 'flask/experimental-area/index';
|
||||
@import 'flask/snaps-authorship-pill/index';
|
||||
@import 'flask/snap-content-footer/index';
|
||||
@import 'flask/snap-install-warning/index';
|
||||
@import 'flask/snap-remove-warning/index';
|
||||
|
1
ui/components/app/flask/snap-authorship/index.js
Normal file
1
ui/components/app/flask/snap-authorship/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './snap-authorship';
|
106
ui/components/app/flask/snap-authorship/snap-authorship.js
Normal file
106
ui/components/app/flask/snap-authorship/snap-authorship.js
Normal file
@ -0,0 +1,106 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { getSnapPrefix } from '@metamask/snaps-utils';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Box from '../../../ui/box';
|
||||
import {
|
||||
BackgroundColor,
|
||||
TextColor,
|
||||
IconColor,
|
||||
FLEX_DIRECTION,
|
||||
TextVariant,
|
||||
BorderColor,
|
||||
AlignItems,
|
||||
DISPLAY,
|
||||
BorderRadius,
|
||||
} from '../../../../helpers/constants/design-system';
|
||||
import {
|
||||
getSnapName,
|
||||
removeSnapIdPrefix,
|
||||
} from '../../../../helpers/utils/util';
|
||||
import {
|
||||
ICON_NAMES,
|
||||
ICON_SIZES,
|
||||
Text,
|
||||
ButtonIcon,
|
||||
} from '../../../component-library';
|
||||
import { getTargetSubjectMetadata } from '../../../../selectors';
|
||||
import SnapAvatar from '../snap-avatar';
|
||||
|
||||
const SnapAuthorship = ({ snapId, className }) => {
|
||||
// We're using optional chaining with snapId, because with the current implementation
|
||||
// of snap update in the snap controller, we do not have reference to snapId when an
|
||||
// update request is rejected because the reference comes from the request itself and not subject metadata
|
||||
// like it is done with snap install
|
||||
const snapPrefix = snapId && getSnapPrefix(snapId);
|
||||
const packageName = snapId && removeSnapIdPrefix(snapId);
|
||||
const isNPM = snapPrefix === 'npm:';
|
||||
const url = isNPM
|
||||
? `https://www.npmjs.com/package/${packageName}`
|
||||
: packageName;
|
||||
|
||||
const subjectMetadata = useSelector((state) =>
|
||||
getTargetSubjectMetadata(state, snapId),
|
||||
);
|
||||
|
||||
const friendlyName = snapId && getSnapName(snapId, subjectMetadata);
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={classnames('snaps-authorship', className)}
|
||||
backgroundColor={BackgroundColor.backgroundDefault}
|
||||
borderColor={BorderColor.borderDefault}
|
||||
borderWidth={1}
|
||||
alignItems={AlignItems.center}
|
||||
paddingLeft={2}
|
||||
paddingTop={2}
|
||||
paddingBottom={2}
|
||||
paddingRight={4}
|
||||
borderRadius={BorderRadius.pill}
|
||||
display={DISPLAY.FLEX}
|
||||
style={{ maxWidth: 'fit-content', width: '100%' }}
|
||||
>
|
||||
<Box>
|
||||
<SnapAvatar snapId={snapId} />
|
||||
</Box>
|
||||
<Box
|
||||
marginLeft={4}
|
||||
marginRight={2}
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
style={{ overflow: 'hidden' }}
|
||||
>
|
||||
<Text ellipsis>{friendlyName}</Text>
|
||||
<Text
|
||||
ellipsis
|
||||
variant={TextVariant.bodySm}
|
||||
color={TextColor.textAlternative}
|
||||
>
|
||||
{packageName}
|
||||
</Text>
|
||||
</Box>
|
||||
<ButtonIcon
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
href={url}
|
||||
iconName={ICON_NAMES.EXPORT}
|
||||
color={IconColor.infoDefault}
|
||||
size={ICON_SIZES.MD}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
SnapAuthorship.propTypes = {
|
||||
/**
|
||||
* The id of the snap
|
||||
*/
|
||||
snapId: PropTypes.string,
|
||||
/**
|
||||
* The className of the SnapAuthorship
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default SnapAuthorship;
|
@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import SnapsAuthorshipPill from '.';
|
||||
import SnapAuthorship from '.';
|
||||
|
||||
export default {
|
||||
title: 'Components/App/Flask/SnapsAuthorshipPill',
|
||||
title: 'Components/App/Flask/SnapAuthorship',
|
||||
|
||||
component: SnapsAuthorshipPill,
|
||||
component: SnapAuthorship,
|
||||
argTypes: {
|
||||
snapId: {
|
||||
control: 'text',
|
||||
@ -12,7 +12,7 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
export const DefaultStory = (args) => <SnapsAuthorshipPill {...args} />;
|
||||
export const DefaultStory = (args) => <SnapAuthorship {...args} />;
|
||||
|
||||
DefaultStory.storyName = 'Default';
|
||||
|
1
ui/components/app/flask/snap-avatar/index.js
Normal file
1
ui/components/app/flask/snap-avatar/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { default } from './snap-avatar';
|
81
ui/components/app/flask/snap-avatar/snap-avatar.js
Normal file
81
ui/components/app/flask/snap-avatar/snap-avatar.js
Normal file
@ -0,0 +1,81 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { useSelector } from 'react-redux';
|
||||
import {
|
||||
TextColor,
|
||||
IconColor,
|
||||
AlignItems,
|
||||
DISPLAY,
|
||||
JustifyContent,
|
||||
Size,
|
||||
} from '../../../../helpers/constants/design-system';
|
||||
import { getSnapName } from '../../../../helpers/utils/util';
|
||||
import {
|
||||
AvatarFavicon,
|
||||
BadgeWrapper,
|
||||
BadgeWrapperPosition,
|
||||
ICON_NAMES,
|
||||
ICON_SIZES,
|
||||
AvatarIcon,
|
||||
AvatarBase,
|
||||
} from '../../../component-library';
|
||||
import { getTargetSubjectMetadata } from '../../../../selectors';
|
||||
|
||||
const SnapAvatar = ({ snapId, className }) => {
|
||||
const subjectMetadata = useSelector((state) =>
|
||||
getTargetSubjectMetadata(state, snapId),
|
||||
);
|
||||
|
||||
const friendlyName = snapId && getSnapName(snapId, subjectMetadata);
|
||||
|
||||
const iconUrl = subjectMetadata?.iconUrl;
|
||||
|
||||
const fallbackIcon = friendlyName && friendlyName[0] ? friendlyName[0] : '?';
|
||||
|
||||
return (
|
||||
<BadgeWrapper
|
||||
className={classnames('snap-avatar', className)}
|
||||
badge={
|
||||
<AvatarIcon
|
||||
iconName={ICON_NAMES.SNAPS}
|
||||
size={ICON_SIZES.XS}
|
||||
backgroundColor={IconColor.infoDefault}
|
||||
iconProps={{
|
||||
size: ICON_SIZES.XS,
|
||||
color: IconColor.infoInverse,
|
||||
}}
|
||||
/>
|
||||
}
|
||||
position={BadgeWrapperPosition.bottomRight}
|
||||
>
|
||||
{iconUrl ? (
|
||||
<AvatarFavicon size={Size.LG} src={iconUrl} />
|
||||
) : (
|
||||
<AvatarBase
|
||||
size={Size.LG}
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={AlignItems.center}
|
||||
justifyContent={JustifyContent.center}
|
||||
color={TextColor.textAlternative}
|
||||
style={{ borderWidth: '0px' }}
|
||||
>
|
||||
{fallbackIcon}
|
||||
</AvatarBase>
|
||||
)}
|
||||
</BadgeWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
SnapAvatar.propTypes = {
|
||||
/**
|
||||
* The id of the snap
|
||||
*/
|
||||
snapId: PropTypes.string,
|
||||
/**
|
||||
* The className of the SnapAvatar
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default SnapAvatar;
|
21
ui/components/app/flask/snap-avatar/snap-avatar.stories.js
Normal file
21
ui/components/app/flask/snap-avatar/snap-avatar.stories.js
Normal file
@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import SnapAvatar from '.';
|
||||
|
||||
export default {
|
||||
title: 'Components/App/Flask/SnapAvatar',
|
||||
|
||||
component: SnapAvatar,
|
||||
argTypes: {
|
||||
snapId: {
|
||||
control: 'text',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const DefaultStory = (args) => <SnapAvatar {...args} />;
|
||||
|
||||
DefaultStory.storyName = 'Default';
|
||||
|
||||
DefaultStory.args = {
|
||||
snapId: 'npm:@metamask/test-snap-bip44',
|
||||
};
|
@ -1 +0,0 @@
|
||||
export { default } from './snaps-authorship-pill';
|
@ -1,37 +0,0 @@
|
||||
@import "design-system";
|
||||
|
||||
.snaps-authorship-pill {
|
||||
display: inline-block;
|
||||
|
||||
.chip {
|
||||
padding-right: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.chip__label {
|
||||
max-width: 168px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
.chip {
|
||||
background-color: var(--color-background-default-hover);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.snaps-authorship-icon {
|
||||
color: var(--color-icon-alternative);
|
||||
}
|
||||
|
||||
.snaps-authorship-version {
|
||||
border-radius: 100px;
|
||||
line-height: 100%;
|
||||
}
|
||||
|
||||
.snaps-authorship-version > span {
|
||||
vertical-align: middle;
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { getSnapPrefix } from '@metamask/snaps-utils';
|
||||
import Chip from '../../../ui/chip';
|
||||
import Box from '../../../ui/box';
|
||||
import Typography from '../../../ui/typography';
|
||||
import {
|
||||
TypographyVariant,
|
||||
TEXT_ALIGN,
|
||||
BackgroundColor,
|
||||
TextColor,
|
||||
} from '../../../../helpers/constants/design-system';
|
||||
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
||||
import {
|
||||
getSnapName,
|
||||
removeSnapIdPrefix,
|
||||
} from '../../../../helpers/utils/util';
|
||||
|
||||
const SnapsAuthorshipPill = ({ snapId, version, className }) => {
|
||||
// We're using optional chaining with snapId, because with the current implementation
|
||||
// of snap update in the snap controller, we do not have reference to snapId when an
|
||||
// update request is rejected because the reference comes from the request itself and not subject metadata
|
||||
// like it is done with snap install
|
||||
const snapPrefix = snapId && getSnapPrefix(snapId);
|
||||
const packageName = snapId && removeSnapIdPrefix(snapId);
|
||||
const isNPM = snapPrefix === 'npm:';
|
||||
const url = isNPM
|
||||
? `https://www.npmjs.com/package/${packageName}`
|
||||
: packageName;
|
||||
const icon = isNPM ? 'fab fa-npm fa-lg' : 'fas fa-code';
|
||||
const t = useI18nContext();
|
||||
|
||||
const friendlyName = getSnapName(snapId);
|
||||
|
||||
return (
|
||||
<a
|
||||
href={url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={classnames(className, `snaps-authorship-pill`)}
|
||||
>
|
||||
<Chip
|
||||
leftIcon={
|
||||
<Box paddingLeft={2}>
|
||||
<i className={`${icon} snaps-authorship-icon`} />
|
||||
</Box>
|
||||
}
|
||||
rightIcon={
|
||||
version && (
|
||||
<Box
|
||||
className="snaps-authorship-version"
|
||||
backgroundColor={BackgroundColor.primaryDefault}
|
||||
paddingLeft={2}
|
||||
paddingRight={2}
|
||||
>
|
||||
<Typography
|
||||
color={TextColor.primaryInverse}
|
||||
variant={TypographyVariant.H7}
|
||||
align={TEXT_ALIGN.CENTER}
|
||||
as="span"
|
||||
className="version"
|
||||
>
|
||||
{t('shorthandVersion', [version])}
|
||||
</Typography>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
backgroundColor={BackgroundColor.backgroundDefault}
|
||||
>
|
||||
<Typography
|
||||
className="chip__label"
|
||||
variant={TypographyVariant.H7}
|
||||
as="span"
|
||||
color={TextColor.textAlternative}
|
||||
title={friendlyName}
|
||||
>
|
||||
{friendlyName}
|
||||
</Typography>
|
||||
</Chip>
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
SnapsAuthorshipPill.propTypes = {
|
||||
/**
|
||||
* The id of the snap
|
||||
*/
|
||||
snapId: PropTypes.string,
|
||||
/**
|
||||
* The version of the snap
|
||||
*/
|
||||
version: PropTypes.string,
|
||||
/**
|
||||
* The className of the SnapsAuthorshipPill
|
||||
*/
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default SnapsAuthorshipPill;
|
@ -8,7 +8,7 @@ import {
|
||||
JustifyContent,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
import SnapsAuthorshipPill from '../flask/snaps-authorship-pill';
|
||||
import SnapAuthorship from '../flask/snap-authorship';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
export default class PermissionsConnectHeader extends Component {
|
||||
@ -82,7 +82,6 @@ export default class PermissionsConnectHeader extends Component {
|
||||
headerText,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
siteOrigin,
|
||||
snapVersion,
|
||||
isSnapInstallOrUpdate,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
} = this.props;
|
||||
@ -97,9 +96,7 @@ export default class PermissionsConnectHeader extends Component {
|
||||
<div className="permissions-connect-header__title">{headerTitle}</div>
|
||||
{
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
isSnapInstallOrUpdate && (
|
||||
<SnapsAuthorshipPill snapId={siteOrigin} version={snapVersion} />
|
||||
)
|
||||
isSnapInstallOrUpdate && <SnapAuthorship snapId={siteOrigin} />
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
}
|
||||
<div className="permissions-connect-header__subtitle">{headerText}</div>
|
||||
|
@ -558,8 +558,14 @@ export function getSnapDerivationPathName(path, curve) {
|
||||
export const removeSnapIdPrefix = (snapId) =>
|
||||
snapId.replace(getSnapPrefix(snapId), '');
|
||||
|
||||
export const getSnapName = (snapId) =>
|
||||
SNAPS_METADATA[snapId]?.name ?? removeSnapIdPrefix(snapId);
|
||||
export const getSnapName = (snapId, subjectMetadata) => {
|
||||
if (SNAPS_METADATA[snapId]?.name) {
|
||||
return SNAPS_METADATA[snapId].name;
|
||||
}
|
||||
|
||||
return subjectMetadata?.name ?? removeSnapIdPrefix(snapId);
|
||||
};
|
||||
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
import { getSnapInstallWarnings } from '../util';
|
||||
import PulseLoader from '../../../../components/ui/pulse-loader/pulse-loader';
|
||||
import InstallError from '../../../../components/app/flask/install-error/install-error';
|
||||
import SnapsAuthorshipPill from '../../../../components/app/flask/snaps-authorship-pill/snaps-authorship-pill';
|
||||
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';
|
||||
@ -88,10 +88,7 @@ export default function SnapInstall({
|
||||
alignItems={AlignItems.center}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
>
|
||||
<SnapsAuthorshipPill
|
||||
snapId={targetSubjectMetadata.origin}
|
||||
version={targetSubjectMetadata.version}
|
||||
/>
|
||||
<SnapAuthorship snapId={targetSubjectMetadata.origin} />
|
||||
{!hasError && (
|
||||
<Text padding={[4, 4, 0, 4]} variant={TextVariant.headingLg}>
|
||||
{t('snapInstall')}
|
||||
|
@ -17,7 +17,7 @@ import {
|
||||
import { Text } from '../../../../components/component-library';
|
||||
import PulseLoader from '../../../../components/ui/pulse-loader/pulse-loader';
|
||||
import InstallError from '../../../../components/app/flask/install-error/install-error';
|
||||
import SnapsAuthorshipPill from '../../../../components/app/flask/snaps-authorship-pill/snaps-authorship-pill';
|
||||
import SnapAuthorship from '../../../../components/app/flask/snap-authorship';
|
||||
import { getSnapName } from '../../../../helpers/utils/util';
|
||||
|
||||
export default function SnapResult({
|
||||
@ -52,10 +52,7 @@ export default function SnapResult({
|
||||
alignItems={AlignItems.center}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
>
|
||||
<SnapsAuthorshipPill
|
||||
snapId={targetSubjectMetadata.origin}
|
||||
version={targetSubjectMetadata.version}
|
||||
/>
|
||||
<SnapAuthorship snapId={targetSubjectMetadata.origin} />
|
||||
{isLoading && (
|
||||
<Box
|
||||
className="loader-container"
|
||||
|
@ -18,7 +18,7 @@ import UpdateSnapPermissionList from '../../../../components/app/flask/update-sn
|
||||
import { getSnapInstallWarnings } from '../util';
|
||||
import PulseLoader from '../../../../components/ui/pulse-loader/pulse-loader';
|
||||
import InstallError from '../../../../components/app/flask/install-error/install-error';
|
||||
import SnapsAuthorshipPill from '../../../../components/app/flask/snaps-authorship-pill/snaps-authorship-pill';
|
||||
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';
|
||||
@ -94,10 +94,7 @@ export default function SnapUpdate({
|
||||
alignItems={AlignItems.center}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
>
|
||||
<SnapsAuthorshipPill
|
||||
snapId={targetSubjectMetadata.origin}
|
||||
version={requestState.newVersion}
|
||||
/>
|
||||
<SnapAuthorship snapId={targetSubjectMetadata.origin} />
|
||||
{!hasError && (
|
||||
<Text padding={[4, 4, 0, 4]} variant={TextVariant.headingLg}>
|
||||
{t('snapUpdate')}
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
FRACTIONS,
|
||||
TextColor,
|
||||
} from '../../../../helpers/constants/design-system';
|
||||
import SnapsAuthorshipPill from '../../../../components/app/flask/snaps-authorship-pill';
|
||||
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';
|
||||
@ -118,7 +118,7 @@ function ViewSnap() {
|
||||
</Typography>
|
||||
<Box className="view-snap__pill-toggle-container">
|
||||
<Box className="view-snap__pill-container" paddingLeft={2}>
|
||||
<SnapsAuthorshipPill snapId={snap.id} />
|
||||
<SnapAuthorship snapId={snap.id} />
|
||||
</Box>
|
||||
<Box paddingLeft={4} className="view-snap__toggle-container">
|
||||
<Tooltip interactive position="bottom" html={t('snapsToggle')}>
|
||||
|
Loading…
x
Reference in New Issue
Block a user