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

chalabi/mobile on desktop #150

Merged
merged 11 commits into from
Jan 6, 2025
Binary file modified bun.lockb
Binary file not shown.
1 change: 0 additions & 1 deletion components/bank/forms/sendForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ export default function SendForm({
amount: [{ denom: values.selectedToken.coreDenom, amount: amountInBaseUnits }],
});

console.log('Estimating fee for address:', address);
const fee = await estimateFee(address, [msg]);

await tx([msg], {
Expand Down
2 changes: 0 additions & 2 deletions components/groups/modals/memberManagementModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,6 @@ export function MemberManagementModal({
weight: member.markedForDeletion ? '0' : member.weight || '1',
}));

console.log('Member updates:', memberUpdates);

const msg = updateGroupMembers({
admin: groupAdmin,
groupId: BigInt(groupId),
Expand Down
167 changes: 137 additions & 30 deletions components/react/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import { WalletStatus } from 'cosmos-kit';
import React, { useCallback, Fragment, useState, useMemo, useEffect } from 'react';
import { Dialog, Transition, Portal } from '@headlessui/react';
import { Connected, Connecting, Error, NotExist, QRCode, WalletList, Contacts } from './views';
import { Connected, Connecting, Error, NotExist, QRCodeView, WalletList, Contacts } from './views';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Avoid shadowing global Error type

The import of Error from ./views shadows the global Error type which could lead to confusion.

Rename the imported component to avoid shadowing:

- import { Connected, Connecting, Error, NotExist, QRCodeView, WalletList, Contacts } from './views';
+ import { Connected, Connecting, ErrorView, NotExist, QRCodeView, WalletList, Contacts } from './views';

Also applies to: 10-11

🧰 Tools
🪛 Biome (1.9.4)

[error] 6-6: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

import { useRouter } from 'next/router';
import { ToastProvider } from '@/contexts/toastContext';
import { useDeviceDetect } from '@/hooks';
import { State, ExpiredError } from '@cosmos-kit/core';

export enum ModalView {
WalletList,
QRCode,
Expand Down Expand Up @@ -35,11 +37,11 @@
showMemberManagementModal = false,
showMessageEditModal = false,
}) => {
const router = useRouter();

const [currentView, setCurrentView] = useState<ModalView>(ModalView.WalletList);
const [qrWallet, setQRWallet] = useState<ChainWalletBase | undefined>();
const [selectedWallet, setSelectedWallet] = useState<ChainWalletBase | undefined>();
const [qrState, setQRState] = useState<State>(State.Init);
const [qrMessage, setQrMessage] = useState<string>('');

const current = walletRepo?.current;
const currentWalletData = current?.walletInfo;
Expand All @@ -58,7 +60,11 @@
setCurrentView(ModalView.WalletList);
break;
case WalletStatus.Connecting:
setCurrentView(ModalView.Connecting);
if (current?.walletInfo.mode === 'wallet-connect' && !isMobile) {
setCurrentView(ModalView.QRCode);
} else {
setCurrentView(ModalView.Connecting);

Check warning on line 66 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L63-L66

Added lines #L63 - L66 were not covered by tests
}
Comment on lines +111 to +115
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Add test coverage for wallet connection modal view states

The verification confirms that there are no existing tests for the wallet connection modal view states. The modal component implements critical view management logic through the ModalView enum, including states for WalletList, QRCode, Connecting, and other wallet-related views, but lacks corresponding test coverage.

Key areas needing test coverage:

  • View transitions based on wallet connection mode (wallet-connect)
  • Mobile vs desktop view handling
  • State management for different wallet connection phases
🔗 Analysis chain

Add test coverage for view management logic

The view management logic for wallet connection states lacks test coverage.

Let's verify the test coverage:

Would you like me to help create test cases for the wallet connection view states?

Also applies to: 84-84

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing test files
fd -e test.tsx -e spec.tsx modal

# Check for wallet connection test patterns
rg -l "describe.*wallet.*connection" -g "*.test.{ts,tsx}"

Length of output: 393


Script:

#!/bin/bash
# Let's check for any existing tests related to the modal component
rg -A 5 "describe.*modal" components/react/__tests__/

# Check if there are any test files in the components/react directory
fd -e test.tsx -e spec.tsx . components/react/

# Look for any wallet-related test patterns in the codebase
rg -l "test.*wallet|describe.*wallet" -g "*.test.{ts,tsx}"

# Check the modal component implementation to understand the test scope better
ast-grep --pattern 'enum ModalView {
  $$$
}'

Length of output: 803

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 63-66: components/react/modal.tsx#L63-L66
Added lines #L63 - L66 were not covered by tests

break;
case WalletStatus.Connected:
setCurrentView(ModalView.Connected);
Expand All @@ -75,32 +81,129 @@
}
}
}
}, [isOpen, walletStatus, currentWalletName, showContacts]);
}, [isOpen, walletStatus, currentWalletName, showContacts, current?.walletInfo.mode, isMobile]);

useEffect(() => {
if (currentView === ModalView.QRCode && qrWallet) {
(qrWallet.client as any)?.setActions?.({
qrUrl: {
state: (s: State) => setQRState(s),
message: (msg: string) => setQrMessage(msg),
},
onError: (err: Error) => {
if (err.message?.includes('No matching key')) {
setQRState(State.Error);
setQrMessage(err.message);
qrWallet.setMessage?.(err.message);
}

Check warning on line 98 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L88-L98

Added lines #L88 - L98 were not covered by tests
},
});

Check warning on line 100 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L100

Added line #L100 was not covered by tests
}
}, [currentView, qrWallet]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for QR code action setup

The QR code action setup could be more robust with proper type checking and error boundaries.

Consider adding error handling:

  useEffect(() => {
    if (currentView === ModalView.QRCode && qrWallet) {
+     try {
        (qrWallet.client as any)?.setActions?.({
          qrUrl: {
            state: (s: State) => setQRState(s),
            message: (msg: string) => setQrMessage(msg),
          },
          onError: (err: Error) => {
            if (err.message?.includes('No matching key')) {
              setQRState(State.Error);
              setQrMessage(err.message);
              qrWallet.setMessage?.(err.message);
            }
          },
        });
+     } catch (error) {
+       console.error('Failed to setup QR code actions:', error);
+       setQRState(State.Error);
+       setQrMessage('Failed to setup QR code connection');
+     }
    }
  }, [currentView, qrWallet]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (currentView === ModalView.QRCode && qrWallet) {
(qrWallet.client as any)?.setActions?.({
qrUrl: {
state: (s: State) => setQRState(s),
message: (msg: string) => setQrMessage(msg),
},
onError: (err: Error) => {
if (err.message?.includes('No matching key')) {
setQRState(State.Error);
setQrMessage(err.message);
qrWallet.setMessage?.(err.message);
}
},
});
}
}, [currentView, qrWallet]);
useEffect(() => {
if (currentView === ModalView.QRCode && qrWallet) {
try {
(qrWallet.client as any)?.setActions?.({
qrUrl: {
state: (s: State) => setQRState(s),
message: (msg: string) => setQrMessage(msg),
},
onError: (err: Error) => {
if (err.message?.includes('No matching key')) {
setQRState(State.Error);
setQrMessage(err.message);
qrWallet.setMessage?.(err.message);
}
},
});
} catch (error) {
console.error('Failed to setup QR code actions:', error);
setQRState(State.Error);
setQrMessage('Failed to setup QR code connection');
}
}
}, [currentView, qrWallet]);
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 88-98: components/react/modal.tsx#L88-L98
Added lines #L88 - L98 were not covered by tests


[warning] 100-100: components/react/modal.tsx#L100
Added line #L100 was not covered by tests


const onWalletClicked = useCallback(
(name: string) => {
walletRepo?.connect(name);
const wallet = walletRepo?.getWallet(name);

Check warning on line 106 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L106

Added line #L106 was not covered by tests

// 1ms timeout prevents _render from determining the view to show first
setTimeout(() => {
const wallet = walletRepo?.getWallet(name);

if (wallet?.isWalletNotExist) {
setCurrentView(ModalView.NotExist);
setSelectedWallet(wallet);
}
if (wallet?.walletInfo.mode === 'wallet-connect') {
setCurrentView(isMobile ? ModalView.Connecting : ModalView.QRCode);
setQRWallet(wallet);
setCurrentView(ModalView.NotExist);
return;

Check warning on line 112 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L111-L112

Added lines #L111 - L112 were not covered by tests
}
}, 1);

if (wallet?.walletInfo.mode === 'wallet-connect') {
if (isMobile) {
setCurrentView(ModalView.Connecting);
walletRepo?.connect(name).catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
});
return;
}

setQRWallet(wallet);
setCurrentView(ModalView.QRCode);

const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
setCurrentView(ModalView.Error);
}
}, 30000);

walletRepo
?.connect(name)
.then(() => {
if (wallet?.walletStatus === WalletStatus.Connected) {
setCurrentView(ModalView.Connected);
}
})
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.QRCode);
setQRState(State.Error);
setQrMessage(error.message);
})
.finally(() => {
clearTimeout(timeoutId);
});

if (qrState === State.Pending && !wallet?.qrUrl?.data) {
setCurrentView(ModalView.Connecting);
}
} else {
setQRWallet(undefined);

setCurrentView(ModalView.Connecting);

const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
setCurrentView(ModalView.Error);
}
}, 30000);

walletRepo
?.connect(name)
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
})
.finally(() => {
clearTimeout(timeoutId);

Check warning on line 175 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L115-L175

Added lines #L115 - L175 were not covered by tests
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Refactor duplicated timeout logic

The wallet connection timeout logic is duplicated for both QR and regular wallet connections.

Extract the timeout logic into a reusable function:

+ const setupConnectionTimeout = (wallet: ChainWalletBase, onTimeout: () => void) => {
+   const timeoutId = setTimeout(() => {
+     if (wallet?.walletStatus === WalletStatus.Connecting) {
+       wallet.disconnect();
+       onTimeout();
+     }
+   }, 30000);
+   return timeoutId;
+ };

  if (wallet?.walletInfo.mode === 'wallet-connect') {
    // ... existing code ...
-   const timeoutId = setTimeout(() => {
-     if (wallet?.walletStatus === WalletStatus.Connecting) {
-       wallet.disconnect();
-       setCurrentView(ModalView.Error);
-     }
-   }, 30000);
+   const timeoutId = setupConnectionTimeout(wallet, () => setCurrentView(ModalView.Error));
    // ... rest of the code ...
  } else {
    // ... existing code ...
-   const timeoutId = setTimeout(() => {
-     if (wallet?.walletStatus === WalletStatus.Connecting) {
-       wallet.disconnect();
-       setCurrentView(ModalView.Error);
-     }
-   }, 30000);
+   const timeoutId = setupConnectionTimeout(wallet, () => setCurrentView(ModalView.Error));
    // ... rest of the code ...
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (wallet?.walletInfo.mode === 'wallet-connect') {
if (isMobile) {
setCurrentView(ModalView.Connecting);
walletRepo?.connect(name).catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
});
return;
}
setQRWallet(wallet);
setCurrentView(ModalView.QRCode);
const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
setCurrentView(ModalView.Error);
}
}, 30000);
walletRepo
?.connect(name)
.then(() => {
if (wallet?.walletStatus === WalletStatus.Connected) {
setCurrentView(ModalView.Connected);
}
})
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.QRCode);
setQRState(State.Error);
setQrMessage(error.message);
})
.finally(() => {
clearTimeout(timeoutId);
});
if (qrState === State.Pending && !wallet?.qrUrl?.data) {
setCurrentView(ModalView.Connecting);
}
} else {
setQRWallet(undefined);
setCurrentView(ModalView.Connecting);
const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
setCurrentView(ModalView.Error);
}
}, 30000);
walletRepo
?.connect(name)
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
})
.finally(() => {
clearTimeout(timeoutId);
});
}
const setupConnectionTimeout = (wallet: ChainWalletBase, onTimeout: () => void) => {
const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
onTimeout();
}
}, 30000);
return timeoutId;
};
if (wallet?.walletInfo.mode === 'wallet-connect') {
if (isMobile) {
setCurrentView(ModalView.Connecting);
walletRepo?.connect(name).catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
});
return;
}
setQRWallet(wallet);
setCurrentView(ModalView.QRCode);
const timeoutId = setupConnectionTimeout(wallet, () => setCurrentView(ModalView.Error));
walletRepo
?.connect(name)
.then(() => {
if (wallet?.walletStatus === WalletStatus.Connected) {
setCurrentView(ModalView.Connected);
}
})
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.QRCode);
setQRState(State.Error);
setQrMessage(error.message);
})
.finally(() => {
clearTimeout(timeoutId);
});
if (qrState === State.Pending && !wallet?.qrUrl?.data) {
setCurrentView(ModalView.Connecting);
}
} else {
setQRWallet(undefined);
setCurrentView(ModalView.Connecting);
const timeoutId = setupConnectionTimeout(wallet, () => setCurrentView(ModalView.Error));
walletRepo
?.connect(name)
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
})
.finally(() => {
clearTimeout(timeoutId);
});
}

},
[walletRepo]
[walletRepo, isMobile, qrState, currentView]
);

useEffect(() => {
if (!isOpen) {
if (qrWallet?.walletStatus === WalletStatus.Connecting) {
qrWallet.disconnect();
setQRWallet(undefined);

Check warning on line 186 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L185-L186

Added lines #L185 - L186 were not covered by tests
}
setQRState(State.Init);
setQrMessage('');
}
}, [isOpen, qrWallet]);

const onCloseModal = useCallback(() => {
if (qrWallet?.walletStatus === WalletStatus.Connecting) {
qrWallet.disconnect();
}

Check warning on line 196 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L194-L196

Added lines #L194 - L196 were not covered by tests
setOpen(false);
}, [setOpen]);
}, [setOpen, qrWallet]);

const onReturnToWalletList = useCallback(() => {
if (qrWallet?.walletStatus === WalletStatus.Connecting) {
qrWallet.disconnect();
setQRWallet(undefined);
}

Check warning on line 204 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L200-L204

Added lines #L200 - L204 were not covered by tests
setCurrentView(ModalView.WalletList);
}, [qrWallet]);

const _render = useMemo(() => {
switch (currentView) {
Expand All @@ -126,11 +229,11 @@
);
case ModalView.Connecting:
let subtitle: string;
if (currentWalletData!.mode === 'wallet-connect') {
subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile.`;
if (currentWalletData!?.mode === 'wallet-connect') {
subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile device.`;

Check warning on line 233 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L232-L233

Added lines #L232 - L233 were not covered by tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unnecessary non-null assertions

The code uses unnecessary non-null assertions (!). Consider using optional chaining instead.

-        if (currentWalletData!?.mode === 'wallet-connect') {
-          subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile device.`;
+        if (currentWalletData?.mode === 'wallet-connect') {
+          subtitle = `Approve ${currentWalletData.prettyName} connection request on your mobile device.`;
         } else {
-          subtitle = `Open the ${currentWalletData!?.prettyName} browser extension to connect your wallet.`;
+          subtitle = `Open the ${currentWalletData?.prettyName} browser extension to connect your wallet.`;
         }

Also applies to: 151-151

🧰 Tools
🪛 Biome (1.9.4)

[error] 147-147: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)

🪛 GitHub Check: codecov/patch

[warning] 147-148: components/react/modal.tsx#L147-L148
Added lines #L147 - L148 were not covered by tests

} else {
subtitle = `Open the ${
currentWalletData!.prettyName
currentWalletData!?.prettyName

Check warning on line 236 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L236

Added line #L236 was not covered by tests
} browser extension to connect your wallet.`;
}

Expand All @@ -146,12 +249,7 @@
);
case ModalView.QRCode:
return (
<QRCode
onClose={onCloseModal}
onReturn={() => setCurrentView(ModalView.WalletList)}
qrUri={qrWallet?.qrUrl.data}
name={qrWallet?.walletInfo.prettyName}
/>
<QRCodeView onClose={onCloseModal} onReturn={onReturnToWalletList} wallet={qrWallet!} />

Check warning on line 252 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L252

Added line #L252 was not covered by tests
);
case ModalView.Error:
return (
Expand Down Expand Up @@ -187,23 +285,32 @@
showMessageEditModal={showMessageEditModal}
/>
);

default:
return (
<div className="flex flex-col items-center justify-center p-6 gap-3">
<p className="text-sm text-gray-600 dark:text-gray-400">Reconnecting your wallet...</p>
<div className="loading loading-ring w-8 h-8 text-primary" />

Check warning on line 293 in components/react/modal.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/modal.tsx#L290-L293

Added lines #L290 - L293 were not covered by tests
</div>
);
}
}, [
currentView,
onCloseModal,
onWalletClicked,
walletRepo,
walletRepo?.wallets,
currentWalletData,
current,
qrWallet?.qrUrl.data,
qrWallet?.walletInfo.prettyName,
router,
onSelect,
currentAddress,
showMemberManagementModal,
showMessageEditModal,
selectedWallet,
qrState,
qrMessage,
qrWallet,
onReturnToWalletList,

currentWalletName,
]);

return (
Expand Down
120 changes: 120 additions & 0 deletions components/react/qrCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import Image from 'next/image';
import QRCodeUtil from 'qrcode';
import React, { FunctionComponent, ReactElement, useMemo } from 'react';

const generateMatrix = (
value: string,
errorCorrectionLevel: QRCodeUtil.QRCodeErrorCorrectionLevel
) => {
const arr = Array.prototype.slice.call(
QRCodeUtil.create(value, { errorCorrectionLevel }).modules.data,
0
);
const sqrt = Math.sqrt(arr.length);
return arr.reduce(
(rows, key, index) =>
(index % sqrt === 0 ? rows.push([key]) : rows[rows.length - 1].push(key)) && rows,
[]
);
};

export const QRCode: FunctionComponent<{
errorCorrectionLevel?: QRCodeUtil.QRCodeErrorCorrectionLevel;
logoUrl?: string;
logoSize?: number;
size?: number;
value: string;
}> = ({ errorCorrectionLevel = 'M', logoSize = 50, logoUrl, size = 280, value }) => {
const dots = useMemo(() => {
const dots: ReactElement[] = [];
const matrix = generateMatrix(value, errorCorrectionLevel);
const cellSize = size / matrix.length;
let qrList = [
{ x: 0, y: 0 },
{ x: 1, y: 0 },
{ x: 0, y: 1 },
];

qrList.forEach(({ x, y }) => {
const x1 = (matrix.length - 7) * cellSize * x;
const y1 = (matrix.length - 7) * cellSize * y;
for (let i = 0; i < 3; i++) {
dots.push(
<rect
fill={i % 2 !== 0 ? 'white' : 'black'}
height={cellSize * (7 - i * 2)}
key={`${i}-${x}-${y}`}
rx={(i - 2) * -5 + (i === 0 ? 2 : 0)} // calculated border radius for corner squares
ry={(i - 2) * -5 + (i === 0 ? 2 : 0)} // calculated border radius for corner squares
width={cellSize * (7 - i * 2)}
x={x1 + cellSize * i}
y={y1 + cellSize * i}
/>
);
}
});

const clearArenaSize = Math.floor(logoSize / cellSize);
const matrixMiddleStart = matrix.length / 2 - clearArenaSize / 2;
const matrixMiddleEnd = matrix.length / 2 + clearArenaSize / 2 - 1;

matrix.forEach((row: QRCodeUtil.QRCode[], i: number) => {
row.forEach((_: any, j: number) => {
if (matrix[i][j]) {
if (
!(
(i < 7 && j < 7) ||
(i > matrix.length - 8 && j < 7) ||
(i < 7 && j > matrix.length - 8)
)
) {
if (
!(
i > matrixMiddleStart &&
i < matrixMiddleEnd &&
j > matrixMiddleStart &&
j < matrixMiddleEnd
)
) {
dots.push(
<circle
cx={i * cellSize + cellSize / 2}
cy={j * cellSize + cellSize / 2}
fill="black"
key={`circle-${i}-${j}`}
r={cellSize / 3} // calculate size of single dots
/>
);
}
}
}
});
});

return dots;
}, [errorCorrectionLevel, logoSize, size, value]);

const logoPosition = size / 2 - logoSize / 2;

return (
<div className="relative flex items-center justify-center rounded-xl bg-white p-4">
<div className="relative" style={{ height: size, width: size }}>
{logoUrl && (
<div
className="absolute flex rounded-lg justify-center"
style={{
top: logoPosition,
width: size,
}}
>
<Image height={logoSize} src={logoUrl} width={logoSize} alt="Wallet logo" />
</div>
)}
<svg height={size} width={size}>
<rect fill="transparent" height={size} width={size} />
{dots}
</svg>
</div>
</div>
);
};
2 changes: 1 addition & 1 deletion components/react/views/Connected.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
<Image
height={0}
width={0}
src={getRealLogo(logo, theme === 'dark')}
src={name === 'Cosmos MetaMask Extension' ? '/metamask.svg' : getRealLogo(logo)}

Check warning on line 62 in components/react/views/Connected.tsx

View check run for this annotation

Codecov / codecov/patch

components/react/views/Connected.tsx#L62

Added line #L62 was not covered by tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add test coverage for MetaMask logo conditional.

The new conditional logic for MetaMask logo handling is currently not covered by tests.

Consider adding test cases to verify:

  1. Logo rendering for Cosmos MetaMask Extension
  2. Logo rendering for other wallet types
describe('Connected component', () => {
  it('should render MetaMask logo for Cosmos MetaMask Extension', () => {
    render(<Connected name="Cosmos MetaMask Extension" logo="some-logo.svg" {...defaultProps} />);
    expect(screen.getByAltText('Cosmos MetaMask Extension')).toHaveAttribute('src', '/metamask.svg');
  });

  it('should render wallet logo for other wallets', () => {
    const logo = 'wallet-logo.svg';
    render(<Connected name="Other Wallet" logo={logo} {...defaultProps} />);
    expect(screen.getByAltText('Other Wallet')).toHaveAttribute('src', getRealLogo(logo));
  });
});
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 60-60: components/react/views/Connected.tsx#L60
Added line #L60 was not covered by tests

alt={name}
className="w-8 h-8 rounded-full mr-2"
/>
Expand Down
Loading
Loading