Skip to content

Commit

Permalink
feat(2808): edit network permissions (#11963)
Browse files Browse the repository at this point in the history
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
add and remove permissions to network



<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
4. What is the improvement/solution?
-->

## **Related issues**

Contributes to solve issue:
MetaMask/MetaMask-planning#2808

## **Manual testing steps**

I have added screenshot below to see how it looks.

Set these following variables in js.env, otherwise none of these screens
will show.
`
export MM_NETWORK_UI_REDESIGN_ENABLED="1"
`
`
export MM_MULTICHAIN_V1_ENABLED="1"
`
`
export MM_CHAIN_PERMISSIONS="1"
`
1. Go to the in-app brower on the mobile wallet, connect to a dapp like
uniswap
2. Click on the icon on top right header, a bottom sheet opens, click on
the manage permissions button
3. Edit permissions, and confirm, when going back to the screen,
permissions should be kept.

## **Screenshots/Recordings**


| Before, user was prompted to give permission | After, user gave
permission and is not prompted to give it |
|--------------|--------------|
| <img width="350" alt="Screenshot 2024-04-18 at 3 56 43 PM"
src="https://github.com/user-attachments/assets/5209ce57-6b39-4f37-a2f3-9a700581ff70">
|<img width="350" alt="Screenshot 2024-04-18s at 3 56 43 PM"
src="https://github.com/user-attachments/assets/c40883eb-458b-418d-8183-02677d812d43">
|



## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---------

Co-authored-by: Alex <[email protected]>
  • Loading branch information
EtherWizard33 and adonesky1 authored Nov 1, 2024
1 parent 771100f commit b8061aa
Show file tree
Hide file tree
Showing 17 changed files with 526 additions and 416 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { StyleSheet } from 'react-native';
const styleSheet = () =>
StyleSheet.create({
networkItemContainer: {
flexDirection: 'row',
alignItems: 'center',
padding: 10,
paddingHorizontal: 10,
paddingVertical: 14,
},
networkAvatar: {
marginHorizontal: 10,
Expand Down
9 changes: 4 additions & 5 deletions app/components/UI/NetworkSelectorList/NetworkSelectorList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const NetworkSelectorList = ({
onSelectNetwork,
networks = [],
isLoading = false,
selectedNetworkIds,
selectedChainIds,
isMultiSelect = true,
renderRightAccessory,
isSelectionDisabled,
Expand All @@ -33,7 +33,6 @@ const NetworkSelectorList = ({
}: NetworkConnectMultiSelectorProps) => {
const networksLengthRef = useRef<number>(0);
const { styles } = useStyles(styleSheet, {});

/**
* Ref for the FlatList component.
* The type of the ref is not explicitly defined.
Expand All @@ -51,8 +50,8 @@ const NetworkSelectorList = ({
? CellVariant.MultiSelect
: CellVariant.Select;
let isSelectedNetwork = isSelected;
if (selectedNetworkIds) {
isSelectedNetwork = selectedNetworkIds.includes(id);
if (selectedChainIds) {
isSelectedNetwork = selectedChainIds.includes(id);
}

return (
Expand All @@ -76,7 +75,7 @@ const NetworkSelectorList = ({
},
[
isLoading,
selectedNetworkIds,
selectedChainIds,
renderRightAccessory,
isSelectionDisabled,
onSelectNetwork,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface NetworkConnectMultiSelectorProps {
onSelectNetwork?: (id: string, isSelected: boolean) => void;
networks?: Network[];
isLoading?: boolean;
selectedNetworkIds?: string[];
selectedChainIds?: string[];
isMultiSelect?: boolean;
renderRightAccessory?: (id: string, name: string) => React.ReactNode;
isSelectionDisabled?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,20 @@ const NetworkVerificationInfo = ({
[customNetworkInformation],
);

const dappOrigin = useMemo(() => {
// @ts-expect-error - The CustomNetworkInformation type is missing the pageMeta property
const customNetworkUrl = customNetworkInformation.pageMeta?.url;
const url = customNetworkUrl ? new URL(customNetworkUrl) : null;
if (url) {
try {
return url.hostname;
} catch (error) {
console.error('Invalid URL:', error);
}
}
return 'Undefined dapp origin';
}, [customNetworkInformation]);

const renderCurrencySymbol = () => (
<>
<Text
Expand Down Expand Up @@ -437,9 +451,7 @@ const NetworkVerificationInfo = ({
{strings(
'switch_custom_network.add_network_and_give_dapp_permission_warning',
{
// @ts-expect-error let's adjust the CustomNetworkInformation after multichain controllers have been updated by the api team
dapp_origin: new URL(customNetworkInformation.pageMeta.url)
?.hostname,
dapp_origin: dappOrigin,
},
)}
</Text>
Expand Down
81 changes: 62 additions & 19 deletions app/components/UI/PermissionsSummary/PermissionsSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import TextComponent, {
TextVariant,
} from '../../../component-library/components/Texts/Text';
import AvatarGroup from '../../../component-library/components/Avatars/AvatarGroup';
import { SAMPLE_AVATARGROUP_PROPS } from '../../../component-library/components/Avatars/AvatarGroup/AvatarGroup.constants';
import Button, {
ButtonSize,
ButtonVariants,
Expand Down Expand Up @@ -57,6 +56,8 @@ const PermissionsSummary = ({
isDisconnectAllShown = true,
isNetworkSwitch = false,
accountAddresses = [],
accounts = [],
networkAvatars = [],
}: PermissionsSummaryProps) => {
const { colors } = useTheme();
const { styles } = useStyles(styleSheet, { isRenderedAsBottomSheet });
Expand Down Expand Up @@ -169,27 +170,56 @@ const PermissionsSummary = ({
if (accountAddresses.length === 0 && selectedAccount) {
return `${strings('permissions.connected_to')} ${selectedAccount.name}`;
}
return accountAddresses.length === 1
? `1 ${strings('accounts.account_connected')}`
: `${accountAddresses.length} ${strings(
'accounts.accounts_connected',
)}`;
if (accountAddresses.length === 1) {
const matchedConnectedAccount = accounts.find(
(account) => account.address === accountAddresses[0],
);
return matchedConnectedAccount?.name;
}

return `${accountAddresses.length} ${strings(
'accounts.accounts_connected',
)}`;
}

if (
accountAddresses.length === 1 ||
(accountAddresses.length === 0 && selectedAccount)
) {
return (
selectedAccount?.name &&
`${strings('permissions.requesting_for')}${selectedAccount?.name}`
if (accountAddresses.length === 1 && accounts?.length >= 1) {
const matchedAccount = accounts.find(
(account) => account.address === accountAddresses[0],
);
return `${strings('permissions.requesting_for')}${
matchedAccount?.name ? matchedAccount.name : accountAddresses[0]
}`;
}

if (accountAddresses.length === 0 && selectedAccount) {
return `${strings('permissions.requesting_for')}${selectedAccount?.name}`;
}

return strings('permissions.requesting_for_accounts', {
numberOfAccounts: accountAddresses.length,
});
}, [accountAddresses, isAlreadyConnected, selectedAccount]);
}, [accountAddresses, isAlreadyConnected, selectedAccount, accounts]);

const getNetworkLabel = useCallback(() => {
if (isAlreadyConnected) {
return networkAvatars.length === 1
? networkAvatars[0]?.name
: `${strings('permissions.n_networks_connect', {
numberOfNetworks: networkAvatars.length,
})}`;
}

if (networkAvatars.length === 1) {
return (
networkAvatars[0]?.name &&
`${strings('permissions.requesting_for')}${networkAvatars[0]?.name}`
);
}

return strings('permissions.requesting_for_networks', {
numberOfNetworks: networkAvatars.length,
});
}, [networkAvatars, isAlreadyConnected]);

function renderAccountPermissionsRequestInfoCard() {
return (
Expand Down Expand Up @@ -280,11 +310,24 @@ const PermissionsSummary = ({
</>
)}
{!isNetworkSwitch && (
<View style={styles.avatarGroup}>
<AvatarGroup
avatarPropsList={SAMPLE_AVATARGROUP_PROPS.avatarPropsList}
/>
</View>
<>
<View style={styles.permissionRequestNetworkName}>
<TextComponent numberOfLines={1} ellipsizeMode="tail">
<TextComponent variant={TextVariant.BodySM}>
{getNetworkLabel()}
</TextComponent>
</TextComponent>
</View>
<View style={styles.avatarGroup}>
<AvatarGroup
// @ts-expect-error - AvatarGroup is not typed
avatarPropsList={networkAvatars.map((avatar) => ({
...avatar,
variant: AvatarVariant.Network,
}))}
/>
</View>
</>
)}
</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { USER_INTENT } from '../../../constants/permissions';
import { Account } from '../../hooks/useAccounts';

export interface PermissionsSummaryProps {
currentPageInformation: {
Expand All @@ -21,5 +22,7 @@ export interface PermissionsSummaryProps {
chainName: string;
chainId: string;
};
accounts?: Account[];
accountAddresses?: string[];
networkAvatars?: ({ name: string; imageSource: string } | null)[];
}
Loading

0 comments on commit b8061aa

Please sign in to comment.