Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Walletconnect multiple key select - enable "Key Switch" setting #2003

Merged
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useGetKeysQuery, useGetLoggedInFingerprintQuery } from '@chia-network/api-react';
import { useGetKeysQuery, useGetLoggedInFingerprintQuery, usePrefs } from '@chia-network/api-react';
import {
ButtonLoading,
DialogActions,
Expand All @@ -8,15 +8,27 @@ import {
Form,
Loading,
useCurrencyCode,
CardListItem,
} from '@chia-network/core';
import { Trans, t } from '@lingui/macro';
import CloseIcon from '@mui/icons-material/Close';
import { Box, Divider, Dialog, DialogContent, DialogTitle, IconButton, Typography, Checkbox } from '@mui/material';
import {
Box,
Divider,
Dialog,
DialogContent,
DialogTitle,
IconButton,
Typography,
Select,
MenuItem,
Checkbox,
Chip,
} from '@mui/material';
import React, { useEffect, useState } from 'react';
import { useForm, useWatch } from 'react-hook-form';

import useWalletConnectContext from '../../hooks/useWalletConnectContext';
import useWalletConnectPreferences from '../../hooks/useWalletConnectPreferences';
paninaro marked this conversation as resolved.
Show resolved Hide resolved

import HeroImage from './images/walletConnectToChia.svg';

Expand All @@ -41,6 +53,8 @@ export default function WalletConnectAddConnectionDialog(props: WalletConnectAdd
const [step, setStep] = useState<Step>(Step.CONNECT);
const { pair, isLoading: isLoadingWallet } = useWalletConnectContext();
const { data: keys, isLoading: isLoadingPublicKeys } = useGetKeysQuery({});
const [sortedWallets] = usePrefs('sortedWallets', []);

const { data: fingerprint, isLoading: isLoadingLoggedInFingerprint } = useGetLoggedInFingerprintQuery();
const mainnet = useCurrencyCode() === 'XCH';
const methods = useForm<FormData>({
Expand All @@ -58,6 +72,20 @@ export default function WalletConnectAddConnectionDialog(props: WalletConnectAdd
defaultValue: [],
});

const { allowConfirmationFingerprintChange, setAllowConfirmationFingerprintChange } = useWalletConnectPreferences();

const sortedKeysMemo = React.useMemo(() => {
const sortedKeys: any[] = sortedWallets
.map((value: string) => (keys || []).find((f: any) => value === String(f.fingerprint)))
.filter((x: any) => !!x); /* if we added a new wallet and order was not saved yet case */
(keys || []).forEach((f: any) => {
if (sortedKeys.map((f2: any) => f2.fingerprint).indexOf(f.fingerprint) === -1) {
sortedKeys.push(f);
}
});
return sortedKeys;
}, [sortedWallets, keys]);

function handleClose() {
onClose();
}
Expand Down Expand Up @@ -85,13 +113,18 @@ export default function WalletConnectAddConnectionDialog(props: WalletConnectAdd
throw new Error(t`Please select at least one key`);
}

if (!allowConfirmationFingerprintChange && fingerprints.length > 1) {
setAllowConfirmationFingerprintChange(true);
}

const topic = await pair(uri, selectedFingerprints, mainnet);
onClose(topic);
}

function handleToggleSelectFingerprint(fingerprintLocal: number) {
const { setValue } = methods;
const { fingerprints } = methods.getValues();
if (fingerprints.length === 1 && fingerprints[0] === fingerprintLocal) return;
const index = fingerprints.indexOf(fingerprintLocal);
if (index === -1) {
setValue('fingerprints', [...fingerprints, fingerprintLocal]);
Expand All @@ -107,6 +140,78 @@ export default function WalletConnectAddConnectionDialog(props: WalletConnectAdd
const isStepValid = step === Step.CONNECT || selectedFingerprints.length > 0;
const canSubmit = !isSubmitting && !isLoading && isStepValid;

function renderKeysMultiSelect() {
return (
<Select
multiple
value={selectedFingerprints}
sx={{
'.MuiSelect-select .Mui-checked': {
display: 'none',
},
}}
native={false}
renderValue={() => t`Select Keys`}
MenuProps={{
PaperProps: {
style: {
maxHeight: '250px',
overflowY: 'auto',
},
},
}}
>
{sortedKeysMemo?.map((key, index) => (
<MenuItem
key={key.fingerprint}
value={key.fingerprint}
onClick={() => handleToggleSelectFingerprint(key.fingerprint)}
sx={{
paddingLeft: '4px',
}}
>
<Checkbox checked={selectedFingerprints.includes(key.fingerprint)} disableRipple />
{key.label || <Trans>Wallet {index + 1}</Trans>} ({key.fingerprint})
</MenuItem>
))}
</Select>
);
}

function renderSelectedAsPills() {
const keysWithIdxs = sortedKeysMemo?.map((key, index) => ({ ...key, idx: index }));
return keysWithIdxs
?.filter((key: any) => selectedFingerprints.indexOf(key.fingerprint) > -1)
.map((key: any) => {
if (selectedFingerprints.length < 2) {
return <Chip label={`${key.label || `${t`Wallet`} ${key.idx + 1}`} (${key.fingerprint})`} />;
}
return (
<Chip
label={`${key.label || `${t`Wallet`} ${key.idx + 1}`} (${key.fingerprint})`}
onDelete={() => {
methods.setValue(
'fingerprints',
selectedFingerprints.filter((f) => f !== key.fingerprint)
);
}}
/>
);
});
}

function renderMultipleKeySelectedWarning() {
const { fingerprints } = methods.getValues();
if (!allowConfirmationFingerprintChange && fingerprints.length > 1) {
return (
<Typography variant="body2" textAlign="center">
<Trans>Warning! Selecting multiple keys will enable "Key Switching" inside Settings / Integration tab.</Trans>
</Typography>
);
}
return null;
}

return (
<Dialog onClose={handleClose} maxWidth="xs" open={open} fullWidth>
<DialogTitle>
Expand Down Expand Up @@ -148,26 +253,12 @@ export default function WalletConnectAddConnectionDialog(props: WalletConnectAdd
) : step === Step.CONNECT ? (
<TextField name="uri" label={<Trans>Paste link</Trans>} multiline required autoFocus />
) : (
<Flex flexDirection="column" gap={2} minWidth={0}>
{keys?.map((key, index) => (
<CardListItem
key={key.fingerprint}
selected={selectedFingerprints.includes(key.fingerprint)}
onSelect={() => handleToggleSelectFingerprint(key.fingerprint)}
>
<Flex flexDirection="row" gap={2} alignItems="center" justifyContent="space-between">
<Flex flexDirection="column" gap={1} minWidth={0}>
<Typography variant="body1" noWrap>
{key.label || <Trans>Wallet {index + 1}</Trans>}
</Typography>
<Typography variant="body2" color="textSecondary">
{key.fingerprint}
</Typography>
</Flex>
<Checkbox checked={selectedFingerprints.includes(key.fingerprint)} disableRipple />
</Flex>
</CardListItem>
))}
<Flex gap={3} flexDirection="column">
{renderMultipleKeySelectedWarning()}
<Flex sx={{ flexWrap: 'wrap' }} gap={1}>
{renderSelectedAsPills()}
</Flex>
{renderKeysMultiSelect()}
</Flex>
)}
</Flex>
Expand Down