chore: improvements

This commit is contained in:
Danish Arora 2024-11-11 16:39:46 +07:00
parent baa5145ff1
commit da8b9c9790
No known key found for this signature in database
GPG Key ID: 1C6EF37CDAE1426E
7 changed files with 95 additions and 24 deletions

View File

@ -43,6 +43,7 @@
"@types/node": "^22.7.6", "@types/node": "^22.7.6",
"@types/react": "^18.3.10", "@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^4.3.2", "@vitejs/plugin-react": "^4.3.2",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"copy-webpack-plugin": "^11.0.0", "copy-webpack-plugin": "^11.0.0",
@ -6610,6 +6611,13 @@
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/ws": { "node_modules/@types/ws": {
"version": "8.5.13", "version": "8.5.13",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",

View File

@ -48,6 +48,7 @@
"@types/node": "^22.7.6", "@types/node": "^22.7.6",
"@types/react": "^18.3.10", "@types/react": "^18.3.10",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"@types/uuid": "^10.0.0",
"@vitejs/plugin-react": "^4.3.2", "@vitejs/plugin-react": "^4.3.2",
"autoprefixer": "^10.4.20", "autoprefixer": "^10.4.20",
"copy-webpack-plugin": "^11.0.0", "copy-webpack-plugin": "^11.0.0",

View File

@ -80,12 +80,13 @@ function App() {
return [...prevChains, message]; return [...prevChains, message];
}); });
} }
setWakuStatus(prev => ({ ...prev, store: 'success' }));
} catch (error) { } catch (error) {
console.error("Error processing message:", error); console.error("Error processing message:", error);
// Update store status to error when query fails
setWakuStatus(prev => ({ ...prev, store: 'error' }));
// Continue processing other messages // Continue processing other messages
} }
setWakuStatus(prev => ({ ...prev, store: 'success' }));
} catch (error) { } catch (error) {
console.error("Error fetching messages from store:", error); console.error("Error fetching messages from store:", error);
setWakuStatus(prev => ({ ...prev, store: 'error' })); setWakuStatus(prev => ({ ...prev, store: 'error' }));

View File

@ -7,9 +7,8 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Di
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Loader2 } from "lucide-react"; import { Loader2 } from "lucide-react";
import QRCode from '@/components/QRCode'; import QRCode from '@/components/QRCode';
import { v4 as uuidv4 } from 'uuid';
import { useWalletPrompt } from '@/hooks/useWalletPrompt'; import { useWalletPrompt } from '@/hooks/useWalletPrompt';
import { v4 as uuidv4 } from 'uuid';
interface SignChainProps { interface SignChainProps {
block: BlockPayload; block: BlockPayload;
chainsData: BlockPayload[]; // Add this prop chainsData: BlockPayload[]; // Add this prop
@ -25,6 +24,7 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
const { data: ensName } = useEnsName({ address }); const { data: ensName } = useEnsName({ address });
const { node } = useWaku<LightNode>(); const { node } = useWaku<LightNode>();
const { ensureWalletConnected } = useWalletPrompt(); const { ensureWalletConnected } = useWalletPrompt();
const [isWalletPrompt, setIsWalletPrompt] = useState(false);
useEffect(() => { useEffect(() => {
if (address) { if (address) {
@ -109,8 +109,13 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
try { try {
if (!address) { if (!address) {
// If not connected, try to connect first // If not connected, try to connect first
setIsWalletPrompt(true);
const connected = await ensureWalletConnected(); const connected = await ensureWalletConnected();
if (!connected) return; setIsWalletPrompt(false);
if (!connected) {
setError('Please ensure your wallet is connected and the app is open.');
return;
}
} }
// Check if already signed // Check if already signed
@ -119,6 +124,13 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
return; return;
} }
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
if (isMobile && typeof window.ethereum === 'undefined') {
setError('Please ensure your wallet app is installed and open before signing.');
window.location.href = 'metamask:///';
return;
}
// Prepare the message // Prepare the message
const message = `Sign Block: const message = `Sign Block:
Chain UUID: ${block.chainUUID} Chain UUID: ${block.chainUUID}
@ -133,8 +145,10 @@ Signed by: ${ensName || address}`;
signMessage({ message }); signMessage({ message });
} catch (error) { } catch (error) {
console.error('Error in sign flow:', error); console.error('Error in sign flow:', error);
setError('Failed to initiate signing. Please try again.'); setError('Failed to initiate signing. Please ensure your wallet app is open and try again.');
setIsSigning(false); setIsSigning(false);
} finally {
setIsWalletPrompt(false);
} }
}; };
@ -161,15 +175,42 @@ Signed by: ${ensName || address}`;
</div> </div>
<QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} /> <QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
</div> </div>
{error && <p className="text-sm text-destructive">{error}</p>} {(error || isWalletPrompt) && (
<div className="space-y-2">
{error && <p className="text-sm text-destructive">{error}</p>}
{isWalletPrompt && (
<div className="rounded-md bg-blue-50 p-4">
<p className="text-sm text-blue-700">
Attempting to connect to your wallet...
</p>
<p className="text-xs text-blue-600 mt-1">
If your wallet doesn't open automatically, please open it manually to approve the connection.
</p>
</div>
)}
{/iPhone|iPad|iPod|Android/i.test(navigator.userAgent) && (
<p className="text-xs text-muted-foreground">
Tip: If your wallet doesn't open automatically, minimize this app and open your wallet manually before trying again.
</p>
)}
</div>
)}
<DialogFooter> <DialogFooter>
<Button variant="secondary" onClick={() => setIsOpen(false)}>Cancel</Button> <Button variant="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
<Button onClick={handleSign} disabled={isSigning || alreadySigned}> <Button
onClick={handleSign}
disabled={isSigning || alreadySigned || isWalletPrompt}
>
{isSigning ? ( {isSigning ? (
<> <>
<Loader2 className="mr-2 h-4 w-4 animate-spin" /> <Loader2 className="mr-2 h-4 w-4 animate-spin" />
Signing... Signing...
</> </>
) : isWalletPrompt ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Connecting...
</>
) : alreadySigned ? ( ) : alreadySigned ? (
'Already Signed' 'Already Signed'
) : !address ? ( ) : !address ? (

View File

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import { Card } from "@/components/ui/card"; import { Card } from "@/components/ui/card";
import { Loader2, CheckCircle2, XCircle } from "lucide-react"; import { Loader2, CheckCircle2, XCircle } from "lucide-react";
import type { Status } from '@/App';
type Status = 'success' | 'error' | 'in-progress';
interface ConnectionStatusProps { interface ConnectionStatusProps {
filter: Status; filter: Status;

View File

@ -82,30 +82,32 @@ const Header: React.FC<HeaderProps> = ({ wakuStatus }) => {
</nav> </nav>
<div className="flex items-center gap-2 md:gap-4"> <div className="flex items-center gap-2 md:gap-4">
<div className="hidden md:flex items-center gap-2"> <div className="flex items-center gap-2">
{!isWakuLoading && !wakuError && ( {!isWakuLoading && !wakuError && (
<> <>
<div className="flex items-center space-x-1"> <div className="flex items-center space-x-1">
<span className="text-muted-foreground">Filter:</span> <span className="hidden md:inline text-muted-foreground">Filter:</span>
<div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${getStatusColor(wakuStatus.filter)}`}></div> <div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${getStatusColor(wakuStatus.filter)}`}></div>
</div> </div>
<div className="flex items-center space-x-1"> <div className="flex items-center space-x-1">
<span className="text-muted-foreground">Store:</span> <span className="hidden md:inline text-muted-foreground">Store:</span>
<div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${getStatusColor(wakuStatus.store)}`}></div> <div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${getStatusColor(wakuStatus.store)}`}></div>
</div> </div>
<div className="flex items-center space-x-1">
<span className="hidden md:inline text-muted-foreground">Peers:</span>
{isWakuLoading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : wakuError ? (
<div className={`w-2 h-2 md:w-3 md:h-3 rounded-full bg-red-500`} />
) : (
<div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${connections > 0 ? "bg-green-500" : "bg-yellow-500"}`} />
)}
</div>
</> </>
)} )}
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{isWakuLoading ? (
<Loader2 className="h-4 w-4 animate-spin" />
) : wakuError ? (
<span className="text-xs text-red-500">Error</span>
) : (
<div className={`w-2 h-2 rounded-full ${connections > 0 ? "bg-green-500" : "bg-yellow-500"}`} />
)}
{isConnected ? ( {isConnected ? (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-xs md:text-sm text-muted-foreground truncate max-w-[80px] md:max-w-[120px]"> <span className="text-xs md:text-sm text-muted-foreground truncate max-w-[80px] md:max-w-[120px]">

View File

@ -7,16 +7,33 @@ export function useWalletPrompt() {
const ensureWalletConnected = async () => { const ensureWalletConnected = async () => {
if (!isConnected) { if (!isConnected) {
try { try {
// Find the first available connector (usually injected/metamask)
const connector = connectors[0] const connector = connectors[0]
if (connector) { if (connector) {
// Check if we're on iOS
const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent)
// If on iOS, try to open MetaMask first
if (isIOS) {
// Attempt to open MetaMask
window.location.href = 'metamask:///'
// Give a small delay before attempting connection
await new Promise(resolve => setTimeout(resolve, 1000))
}
await connect({ connector }) await connect({ connector })
// Wait a brief moment for the connection to be established
await new Promise(resolve => setTimeout(resolve, 1000))
return true
} }
// Wait a brief moment for the connection to be established
await new Promise(resolve => setTimeout(resolve, 1000));
return true
} catch (error) { } catch (error) {
console.error('Error connecting wallet:', error) console.error('Error connecting wallet:', error)
// If connection fails, try to open MetaMask directly
if (typeof window.ethereum === 'undefined') {
// Redirect to MetaMask download page if not installed
window.open('https://metamask.io/download/', '_blank')
}
return false return false
} }
} }