2023-03-24 17:16:46 +01:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import classnames from 'classnames';
|
|
|
|
import { getSnapPrefix } from '@metamask/snaps-utils';
|
2023-04-25 19:20:37 +02:00
|
|
|
import { useDispatch, useSelector } from 'react-redux';
|
2023-03-24 17:16:46 +01:00
|
|
|
import Box from '../../../ui/box';
|
|
|
|
import {
|
|
|
|
BackgroundColor,
|
|
|
|
TextColor,
|
|
|
|
FLEX_DIRECTION,
|
|
|
|
TextVariant,
|
|
|
|
BorderColor,
|
|
|
|
AlignItems,
|
|
|
|
DISPLAY,
|
2023-04-03 18:04:30 +02:00
|
|
|
BLOCK_SIZES,
|
2023-04-25 19:20:37 +02:00
|
|
|
JustifyContent,
|
|
|
|
BorderStyle,
|
|
|
|
Color,
|
|
|
|
BorderRadius,
|
2023-03-24 17:16:46 +01:00
|
|
|
} from '../../../../helpers/constants/design-system';
|
|
|
|
import {
|
2023-04-25 19:20:37 +02:00
|
|
|
formatDate,
|
2023-03-24 17:16:46 +01:00
|
|
|
getSnapName,
|
|
|
|
removeSnapIdPrefix,
|
|
|
|
} from '../../../../helpers/utils/util';
|
2023-04-19 23:16:49 +02:00
|
|
|
|
2023-04-25 19:20:37 +02:00
|
|
|
import { Text, ButtonLink } from '../../../component-library';
|
2023-03-24 17:16:46 +01:00
|
|
|
import { getTargetSubjectMetadata } from '../../../../selectors';
|
|
|
|
import SnapAvatar from '../snap-avatar';
|
2023-04-25 19:20:37 +02:00
|
|
|
import { useI18nContext } from '../../../../hooks/useI18nContext';
|
|
|
|
import Tooltip from '../../../ui/tooltip/tooltip';
|
|
|
|
import ToggleButton from '../../../ui/toggle-button';
|
|
|
|
import { disableSnap, enableSnap } from '../../../../store/actions';
|
|
|
|
import { useOriginMetadata } from '../../../../hooks/useOriginMetadata';
|
|
|
|
import SnapVersion from '../snap-version/snap-version';
|
|
|
|
|
|
|
|
const SnapAuthorship = ({ snapId, className, expanded = false, snap }) => {
|
|
|
|
const t = useI18nContext();
|
|
|
|
const dispatch = useDispatch();
|
2023-03-24 17:16:46 +01:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2023-04-25 19:20:37 +02:00
|
|
|
// Expanded data
|
|
|
|
const versionHistory = snap?.versionHistory ?? [];
|
|
|
|
const installInfo = versionHistory.length
|
|
|
|
? versionHistory[versionHistory.length - 1]
|
|
|
|
: undefined;
|
|
|
|
const installOrigin = useOriginMetadata(installInfo?.origin);
|
|
|
|
|
|
|
|
const onToggle = () => {
|
|
|
|
if (snap?.enabled) {
|
|
|
|
dispatch(disableSnap(snap?.id));
|
|
|
|
} else {
|
|
|
|
dispatch(enableSnap(snap?.id));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-03-24 17:16:46 +01:00
|
|
|
return (
|
|
|
|
<Box
|
|
|
|
className={classnames('snaps-authorship', className)}
|
|
|
|
backgroundColor={BackgroundColor.backgroundDefault}
|
|
|
|
borderColor={BorderColor.borderDefault}
|
|
|
|
borderWidth={1}
|
2023-04-03 18:04:30 +02:00
|
|
|
width={BLOCK_SIZES.FULL}
|
2023-04-25 19:20:37 +02:00
|
|
|
borderRadius={expanded ? BorderRadius.LG : BorderRadius.pill}
|
2023-03-24 17:16:46 +01:00
|
|
|
>
|
|
|
|
<Box
|
2023-04-25 19:20:37 +02:00
|
|
|
alignItems={AlignItems.center}
|
2023-03-24 17:16:46 +01:00
|
|
|
display={DISPLAY.FLEX}
|
2023-04-25 19:20:37 +02:00
|
|
|
width={BLOCK_SIZES.FULL}
|
|
|
|
paddingLeft={expanded ? 4 : 2}
|
|
|
|
paddingRight={expanded ? 4 : 2}
|
|
|
|
paddingTop={expanded ? 3 : 1}
|
|
|
|
paddingBottom={expanded ? 3 : 1}
|
2023-03-24 17:16:46 +01:00
|
|
|
>
|
2023-04-25 19:20:37 +02:00
|
|
|
<Box>
|
|
|
|
<SnapAvatar snapId={snapId} />
|
|
|
|
</Box>
|
|
|
|
<Box
|
|
|
|
marginLeft={2}
|
|
|
|
marginRight={expanded ? 0 : 2}
|
|
|
|
display={DISPLAY.FLEX}
|
|
|
|
flexDirection={FLEX_DIRECTION.COLUMN}
|
|
|
|
style={{ overflow: 'hidden' }}
|
2023-03-24 17:16:46 +01:00
|
|
|
>
|
2023-04-25 19:20:37 +02:00
|
|
|
<Text ellipsis>{friendlyName}</Text>
|
|
|
|
<Text
|
|
|
|
ellipsis
|
|
|
|
variant={TextVariant.bodySm}
|
|
|
|
color={TextColor.textAlternative}
|
|
|
|
>
|
|
|
|
{packageName}
|
|
|
|
</Text>
|
|
|
|
</Box>
|
|
|
|
{!expanded && (
|
|
|
|
<Box marginLeft="auto">
|
|
|
|
<SnapVersion version={subjectMetadata?.version} url={url} />
|
|
|
|
</Box>
|
|
|
|
)}
|
2023-03-24 17:16:46 +01:00
|
|
|
</Box>
|
2023-04-25 19:20:37 +02:00
|
|
|
{expanded && (
|
|
|
|
<Box flexDirection={FLEX_DIRECTION.COLUMN} width={BLOCK_SIZES.FULL}>
|
|
|
|
<Box
|
|
|
|
flexDirection={FLEX_DIRECTION.ROW}
|
|
|
|
justifyContent={JustifyContent.spaceBetween}
|
|
|
|
paddingLeft={4}
|
|
|
|
paddingTop={4}
|
|
|
|
paddingBottom={4}
|
|
|
|
borderColor={BorderColor.borderDefault}
|
|
|
|
width={BLOCK_SIZES.FULL}
|
|
|
|
style={{
|
|
|
|
borderLeft: BorderStyle.none,
|
|
|
|
borderRight: BorderStyle.none,
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Text variant={TextVariant.bodyMdBold}>{t('enableSnap')}</Text>
|
|
|
|
<Box style={{ maxWidth: '52px' }}>
|
|
|
|
<Tooltip interactive position="left" html={t('snapsToggle')}>
|
|
|
|
<ToggleButton value={snap?.enabled} onToggle={onToggle} />
|
|
|
|
</Tooltip>
|
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
<Box
|
|
|
|
flexDirection={FLEX_DIRECTION.COLUMN}
|
|
|
|
padding={4}
|
|
|
|
width={BLOCK_SIZES.FULL}
|
|
|
|
>
|
|
|
|
{installOrigin && installInfo && (
|
|
|
|
<Box
|
|
|
|
flexDirection={FLEX_DIRECTION.ROW}
|
|
|
|
justifyContent={JustifyContent.spaceBetween}
|
|
|
|
width={BLOCK_SIZES.FULL}
|
|
|
|
>
|
|
|
|
<Text variant={TextVariant.bodyMdBold}>
|
|
|
|
{t('installOrigin')}
|
|
|
|
</Text>
|
|
|
|
<Box
|
|
|
|
flexDirection={FLEX_DIRECTION.COLUMN}
|
|
|
|
alignItems={AlignItems.flexEnd}
|
|
|
|
>
|
|
|
|
<ButtonLink href={installOrigin.origin} target="_blank">
|
|
|
|
{installOrigin.host}
|
|
|
|
</ButtonLink>
|
|
|
|
<Text color={Color.textMuted}>
|
|
|
|
{t('installedOn', [
|
|
|
|
formatDate(installInfo.date, 'dd MMM yyyy'),
|
|
|
|
])}
|
|
|
|
</Text>
|
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
)}
|
|
|
|
<Box
|
|
|
|
flexDirection={FLEX_DIRECTION.ROW}
|
|
|
|
justifyContent={JustifyContent.spaceBetween}
|
|
|
|
alignItems={AlignItems.center}
|
|
|
|
marginTop={4}
|
|
|
|
>
|
|
|
|
<Text variant={TextVariant.bodyMdBold}>{t('version')}</Text>
|
|
|
|
<SnapVersion version={snap?.version} url={url} />
|
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
)}
|
2023-03-24 17:16:46 +01:00
|
|
|
</Box>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
SnapAuthorship.propTypes = {
|
|
|
|
/**
|
|
|
|
* The id of the snap
|
|
|
|
*/
|
|
|
|
snapId: PropTypes.string,
|
|
|
|
/**
|
|
|
|
* The className of the SnapAuthorship
|
|
|
|
*/
|
|
|
|
className: PropTypes.string,
|
2023-04-25 19:20:37 +02:00
|
|
|
/**
|
|
|
|
* If the authorship component should be expanded
|
|
|
|
*/
|
|
|
|
expanded: PropTypes.bool,
|
|
|
|
/**
|
|
|
|
* The snap object. Can be undefined if the component is not expanded
|
|
|
|
*/
|
|
|
|
snap: PropTypes.object,
|
2023-03-24 17:16:46 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
export default SnapAuthorship;
|