mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Fix v10.11: Unable to find value of key "eth_accounts" for locale "en" in Permissions Modal (#13833)
* ConnectedAccountsPermissions: convert to FC * permissions: add usePermissionsDescriptions - fix ConnectedAccountsPermissions eth_accounts i18n * ConnectedAccountsPermissions: rm .component from path * ConnectedAccountsPermissions: fix toggleExpanded ensure we change previous state value Co-authored-by: Mark Stacey <markjstacey@gmail.com> Co-authored-by: Mark Stacey <markjstacey@gmail.com>
This commit is contained in:
parent
395806943f
commit
aa89bb189b
@ -1,86 +0,0 @@
|
|||||||
import classnames from 'classnames';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import React, { PureComponent } from 'react';
|
|
||||||
import CheckBox from '../../ui/check-box';
|
|
||||||
|
|
||||||
export default class ConnectedAccountsPermissions extends PureComponent {
|
|
||||||
static contextTypes = {
|
|
||||||
t: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
static defaultProps = {
|
|
||||||
permissions: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
permissions: PropTypes.arrayOf(
|
|
||||||
PropTypes.shape({
|
|
||||||
key: PropTypes.string.isRequired,
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {
|
|
||||||
expanded: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
toggleExpanded = () => {
|
|
||||||
this.setState((prevState) => ({
|
|
||||||
expanded: !prevState.expanded,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { permissions } = this.props;
|
|
||||||
const { t } = this.context;
|
|
||||||
const { expanded } = this.state;
|
|
||||||
|
|
||||||
if (permissions.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="connected-accounts-permissions">
|
|
||||||
<p
|
|
||||||
className="connected-accounts-permissions__header"
|
|
||||||
onClick={this.toggleExpanded}
|
|
||||||
>
|
|
||||||
<strong>{t('permissions')}</strong>
|
|
||||||
<button
|
|
||||||
className={classnames('fas', {
|
|
||||||
'fa-angle-down': !expanded,
|
|
||||||
'fa-angle-up': expanded,
|
|
||||||
})}
|
|
||||||
title={t('showPermissions')}
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
<div
|
|
||||||
className={classnames(
|
|
||||||
'connected-accounts-permissions__list-container',
|
|
||||||
{
|
|
||||||
'connected-accounts-permissions__list-container--expanded': expanded,
|
|
||||||
},
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<p>{t('authorizedPermissions')}:</p>
|
|
||||||
<ul className="connected-accounts-permissions__list">
|
|
||||||
{permissions.map(({ key: permissionName }) => (
|
|
||||||
<li
|
|
||||||
key={permissionName}
|
|
||||||
className="connected-accounts-permissions__list-item"
|
|
||||||
>
|
|
||||||
<CheckBox
|
|
||||||
checked
|
|
||||||
disabled
|
|
||||||
id={permissionName}
|
|
||||||
className="connected-accounts-permissions__checkbox"
|
|
||||||
/>
|
|
||||||
<label htmlFor={permissionName}>{t(permissionName)}</label>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,83 @@
|
|||||||
|
import classnames from 'classnames';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import CheckBox from '../../ui/check-box';
|
||||||
|
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||||
|
import { usePermissionDescriptions } from '../../../hooks/usePermissionDescriptions';
|
||||||
|
|
||||||
|
const ConnectedAccountsPermissions = ({ permissions }) => {
|
||||||
|
const t = useI18nContext();
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
|
||||||
|
const getPermissionDescription = usePermissionDescriptions();
|
||||||
|
|
||||||
|
const toggleExpanded = () => {
|
||||||
|
setExpanded((_expanded) => !_expanded);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!permissions.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="connected-accounts-permissions">
|
||||||
|
<p
|
||||||
|
className="connected-accounts-permissions__header"
|
||||||
|
onClick={toggleExpanded}
|
||||||
|
>
|
||||||
|
<strong>{t('permissions')}</strong>
|
||||||
|
<button
|
||||||
|
className={classnames('fas', {
|
||||||
|
'fa-angle-down': !expanded,
|
||||||
|
'fa-angle-up': expanded,
|
||||||
|
})}
|
||||||
|
title={t('showPermissions')}
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
className={classnames(
|
||||||
|
'connected-accounts-permissions__list-container',
|
||||||
|
{
|
||||||
|
'connected-accounts-permissions__list-container--expanded': expanded,
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<p>{t('authorizedPermissions')}:</p>
|
||||||
|
<ul className="connected-accounts-permissions__list">
|
||||||
|
{permissions.map(({ key: permissionName }) => (
|
||||||
|
<li
|
||||||
|
key={permissionName}
|
||||||
|
className="connected-accounts-permissions__list-item"
|
||||||
|
>
|
||||||
|
<CheckBox
|
||||||
|
checked
|
||||||
|
disabled
|
||||||
|
id={permissionName}
|
||||||
|
className="connected-accounts-permissions__checkbox"
|
||||||
|
/>
|
||||||
|
<label htmlFor={permissionName}>
|
||||||
|
{getPermissionDescription(permissionName).label}
|
||||||
|
</label>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ConnectedAccountsPermissions.propTypes = {
|
||||||
|
permissions: PropTypes.arrayOf(
|
||||||
|
PropTypes.shape({
|
||||||
|
key: PropTypes.string.isRequired,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
ConnectedAccountsPermissions.defaultProps = {
|
||||||
|
permissions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
ConnectedAccountsPermissions.displayName = 'ConnectedAccountsPermissions';
|
||||||
|
|
||||||
|
export default React.memo(ConnectedAccountsPermissions);
|
@ -1 +1 @@
|
|||||||
export { default } from './connected-accounts-permissions.component';
|
export { default } from './connected-accounts-permissions';
|
||||||
|
@ -1,116 +1,16 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import {
|
import { usePermissionDescriptions } from '../../../hooks/usePermissionDescriptions';
|
||||||
RestrictedMethods,
|
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
|
||||||
EndowmentPermissions,
|
|
||||||
PermissionNamespaces,
|
|
||||||
///: END:ONLY_INCLUDE_IN
|
|
||||||
} from '../../../../shared/constants/permissions';
|
|
||||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
|
||||||
import { coinTypeToProtocolName } from '../../../helpers/utils/util';
|
|
||||||
///: END:ONLY_INCLUDE_IN
|
|
||||||
|
|
||||||
const UNKNOWN_PERMISSION = Symbol('unknown');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} PermissionLabelObject
|
|
||||||
* @property {string} label - The text label.
|
|
||||||
* @property {string} leftIcon - The left icon.
|
|
||||||
* @property {string} rightIcon - The right icon.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the permission list label dictionary key for the specified permission
|
|
||||||
* name.
|
|
||||||
*
|
|
||||||
* @param {string} permissionName - The name of the permission whose key to
|
|
||||||
* retrieve.
|
|
||||||
* @param {Record<string, PermissionLabelObject>} permissionDictionary - The
|
|
||||||
* dictionary object mapping permission keys to label objects.
|
|
||||||
*/
|
|
||||||
function getPermissionKey(permissionName, permissionDictionary) {
|
|
||||||
if (Object.hasOwnProperty.call(permissionDictionary, permissionName)) {
|
|
||||||
return permissionName;
|
|
||||||
}
|
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
|
||||||
for (const namespace of Object.keys(PermissionNamespaces)) {
|
|
||||||
if (permissionName.startsWith(namespace)) {
|
|
||||||
return PermissionNamespaces[namespace];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
///: END:ONLY_INCLUDE_IN
|
|
||||||
|
|
||||||
return UNKNOWN_PERMISSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function PermissionsConnectPermissionList({ permissions }) {
|
export default function PermissionsConnectPermissionList({ permissions }) {
|
||||||
const t = useI18nContext();
|
const getPermissionDescription = usePermissionDescriptions();
|
||||||
|
|
||||||
const PERMISSION_LIST_VALUES = useMemo(() => {
|
|
||||||
return {
|
|
||||||
[RestrictedMethods.eth_accounts]: {
|
|
||||||
leftIcon: 'fas fa-eye',
|
|
||||||
label: t('permission_ethereumAccounts'),
|
|
||||||
rightIcon: null,
|
|
||||||
},
|
|
||||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
|
||||||
[RestrictedMethods.snap_confirm]: {
|
|
||||||
leftIcon: 'fas fa-user-check',
|
|
||||||
label: t('permission_customConfirmation'),
|
|
||||||
rightIcon: null,
|
|
||||||
},
|
|
||||||
[RestrictedMethods['snap_getBip44Entropy_*']]: (permissionName) => {
|
|
||||||
const coinType = permissionName.split('_').slice(-1);
|
|
||||||
return {
|
|
||||||
leftIcon: 'fas fa-door-open',
|
|
||||||
label: t('permission_manageBip44Keys', [
|
|
||||||
coinTypeToProtocolName(coinType) ||
|
|
||||||
`${coinType} (Unrecognized protocol)`,
|
|
||||||
]),
|
|
||||||
rightIcon: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
[RestrictedMethods.snap_manageState]: {
|
|
||||||
leftIcon: 'fas fa-download',
|
|
||||||
label: t('permission_manageState'),
|
|
||||||
rightIcon: null,
|
|
||||||
},
|
|
||||||
[RestrictedMethods['wallet_snap_*']]: (permissionName) => {
|
|
||||||
const snapId = permissionName.split('_').slice(-1);
|
|
||||||
return {
|
|
||||||
leftIcon: 'fas fa-bolt',
|
|
||||||
label: t('permission_accessSnap', [snapId]),
|
|
||||||
rightIcon: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
[EndowmentPermissions['endowment:network-access']]: {
|
|
||||||
leftIcon: 'fas fa-wifi',
|
|
||||||
label: t('permission_accessNetwork'),
|
|
||||||
rightIcon: null,
|
|
||||||
},
|
|
||||||
///: END:ONLY_INCLUDE_IN
|
|
||||||
[UNKNOWN_PERMISSION]: (permissionName) => {
|
|
||||||
return {
|
|
||||||
leftIcon: 'fas fa-times-circle',
|
|
||||||
label: t('permission_unknown', [permissionName ?? 'undefined']),
|
|
||||||
rightIcon: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}, [t]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="permissions-connect-permission-list">
|
<div className="permissions-connect-permission-list">
|
||||||
{Object.keys(permissions).map((permission) => {
|
{Object.keys(permissions).map((permission) => {
|
||||||
const listValue =
|
const { label, leftIcon, rightIcon } = getPermissionDescription(
|
||||||
PERMISSION_LIST_VALUES[
|
permission,
|
||||||
getPermissionKey(permission, PERMISSION_LIST_VALUES)
|
);
|
||||||
];
|
|
||||||
|
|
||||||
const { label, leftIcon, rightIcon } =
|
|
||||||
typeof listValue === 'function' ? listValue(permission) : listValue;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="permission" key={permission}>
|
<div className="permission" key={permission}>
|
||||||
|
98
ui/hooks/usePermissionDescriptions.js
Normal file
98
ui/hooks/usePermissionDescriptions.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import {
|
||||||
|
RestrictedMethods,
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
EndowmentPermissions,
|
||||||
|
PermissionNamespaces,
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
} from '../../shared/constants/permissions';
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
import { coinTypeToProtocolName } from '../helpers/utils/util';
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
import { useI18nContext } from './useI18nContext';
|
||||||
|
|
||||||
|
const UNKNOWN_PERMISSION = Symbol('unknown');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PermissionLabelObject
|
||||||
|
* @property {string} label - The text label.
|
||||||
|
* @property {string} leftIcon - The left icon.
|
||||||
|
* @property {string} rightIcon - The right icon.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {(permissionName:string) => PermissionLabelObject}
|
||||||
|
*/
|
||||||
|
export const usePermissionDescriptions = () => {
|
||||||
|
const t = useI18nContext();
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
const permissionDescriptions = {
|
||||||
|
[RestrictedMethods.eth_accounts]: {
|
||||||
|
leftIcon: 'fas fa-eye',
|
||||||
|
label: t('permission_ethereumAccounts'),
|
||||||
|
rightIcon: null,
|
||||||
|
},
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
[RestrictedMethods.snap_confirm]: {
|
||||||
|
leftIcon: 'fas fa-user-check',
|
||||||
|
label: t('permission_customConfirmation'),
|
||||||
|
rightIcon: null,
|
||||||
|
},
|
||||||
|
[RestrictedMethods['snap_getBip44Entropy_*']]: (permissionName) => {
|
||||||
|
const coinType = permissionName.split('_').slice(-1);
|
||||||
|
return {
|
||||||
|
leftIcon: 'fas fa-door-open',
|
||||||
|
label: t('permission_manageBip44Keys', [
|
||||||
|
coinTypeToProtocolName(coinType) ||
|
||||||
|
`${coinType} (Unrecognized protocol)`,
|
||||||
|
]),
|
||||||
|
rightIcon: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[RestrictedMethods.snap_manageState]: {
|
||||||
|
leftIcon: 'fas fa-download',
|
||||||
|
label: t('permission_manageState'),
|
||||||
|
rightIcon: null,
|
||||||
|
},
|
||||||
|
[RestrictedMethods['wallet_snap_*']]: (permissionName) => {
|
||||||
|
const snapId = permissionName.split('_').slice(-1);
|
||||||
|
return {
|
||||||
|
leftIcon: 'fas fa-bolt',
|
||||||
|
label: t('permission_accessSnap', [snapId]),
|
||||||
|
rightIcon: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[EndowmentPermissions['endowment:network-access']]: {
|
||||||
|
leftIcon: 'fas fa-wifi',
|
||||||
|
label: t('permission_accessNetwork'),
|
||||||
|
rightIcon: null,
|
||||||
|
},
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
[UNKNOWN_PERMISSION]: (permissionName) => {
|
||||||
|
return {
|
||||||
|
leftIcon: 'fas fa-times-circle',
|
||||||
|
label: t('permission_unknown', [permissionName ?? 'undefined']),
|
||||||
|
rightIcon: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return (permissionName) => {
|
||||||
|
let value = permissionDescriptions[UNKNOWN_PERMISSION];
|
||||||
|
|
||||||
|
if (Object.hasOwnProperty.call(permissionDescriptions, permissionName)) {
|
||||||
|
value = permissionDescriptions[permissionName];
|
||||||
|
}
|
||||||
|
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||||
|
for (const namespace of Object.keys(PermissionNamespaces)) {
|
||||||
|
if (permissionName.startsWith(namespace)) {
|
||||||
|
value = permissionDescriptions[PermissionNamespaces[namespace]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///: END:ONLY_INCLUDE_IN
|
||||||
|
|
||||||
|
return typeof value === 'function' ? value(permissionName) : value;
|
||||||
|
};
|
||||||
|
}, [t]);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user