mirror of https://github.com/waku-org/waku-lab.git
chore: improvements
This commit is contained in:
parent
baa5145ff1
commit
da8b9c9790
|
@ -43,6 +43,7 @@
|
|||
"@types/node": "^22.7.6",
|
||||
"@types/react": "^18.3.10",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vitejs/plugin-react": "^4.3.2",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
|
@ -6610,6 +6611,13 @@
|
|||
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
|
||||
"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": {
|
||||
"version": "8.5.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz",
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
"@types/node": "^22.7.6",
|
||||
"@types/react": "^18.3.10",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@vitejs/plugin-react": "^4.3.2",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
|
|
|
@ -80,12 +80,13 @@ function App() {
|
|||
return [...prevChains, message];
|
||||
});
|
||||
}
|
||||
setWakuStatus(prev => ({ ...prev, store: 'success' }));
|
||||
} catch (error) {
|
||||
console.error("Error processing message:", error);
|
||||
// Update store status to error when query fails
|
||||
setWakuStatus(prev => ({ ...prev, store: 'error' }));
|
||||
// Continue processing other messages
|
||||
}
|
||||
|
||||
setWakuStatus(prev => ({ ...prev, store: 'success' }));
|
||||
} catch (error) {
|
||||
console.error("Error fetching messages from store:", error);
|
||||
setWakuStatus(prev => ({ ...prev, store: 'error' }));
|
||||
|
|
|
@ -7,9 +7,8 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Di
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { Loader2 } from "lucide-react";
|
||||
import QRCode from '@/components/QRCode';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { useWalletPrompt } from '@/hooks/useWalletPrompt';
|
||||
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
interface SignChainProps {
|
||||
block: BlockPayload;
|
||||
chainsData: BlockPayload[]; // Add this prop
|
||||
|
@ -25,6 +24,7 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||
const { data: ensName } = useEnsName({ address });
|
||||
const { node } = useWaku<LightNode>();
|
||||
const { ensureWalletConnected } = useWalletPrompt();
|
||||
const [isWalletPrompt, setIsWalletPrompt] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (address) {
|
||||
|
@ -109,8 +109,13 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||
try {
|
||||
if (!address) {
|
||||
// If not connected, try to connect first
|
||||
setIsWalletPrompt(true);
|
||||
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
|
||||
|
@ -119,6 +124,13 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||
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
|
||||
const message = `Sign Block:
|
||||
Chain UUID: ${block.chainUUID}
|
||||
|
@ -133,8 +145,10 @@ Signed by: ${ensName || address}`;
|
|||
signMessage({ message });
|
||||
} catch (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);
|
||||
} finally {
|
||||
setIsWalletPrompt(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -161,15 +175,42 @@ Signed by: ${ensName || address}`;
|
|||
</div>
|
||||
<QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
|
||||
</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>
|
||||
<Button variant="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
|
||||
<Button onClick={handleSign} disabled={isSigning || alreadySigned}>
|
||||
<Button
|
||||
onClick={handleSign}
|
||||
disabled={isSigning || alreadySigned || isWalletPrompt}
|
||||
>
|
||||
{isSigning ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Signing...
|
||||
</>
|
||||
) : isWalletPrompt ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
Connecting...
|
||||
</>
|
||||
) : alreadySigned ? (
|
||||
'Already Signed'
|
||||
) : !address ? (
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React from 'react';
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Loader2, CheckCircle2, XCircle } from "lucide-react";
|
||||
import type { Status } from '@/App';
|
||||
|
||||
type Status = 'success' | 'error' | 'in-progress';
|
||||
|
||||
interface ConnectionStatusProps {
|
||||
filter: Status;
|
||||
|
|
|
@ -82,30 +82,32 @@ const Header: React.FC<HeaderProps> = ({ wakuStatus }) => {
|
|||
</nav>
|
||||
|
||||
<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 && (
|
||||
<>
|
||||
<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>
|
||||
<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>
|
||||
<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 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 ? (
|
||||
<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]">
|
||||
|
|
|
@ -7,16 +7,33 @@ export function useWalletPrompt() {
|
|||
const ensureWalletConnected = async () => {
|
||||
if (!isConnected) {
|
||||
try {
|
||||
// Find the first available connector (usually injected/metamask)
|
||||
const connector = connectors[0]
|
||||
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 })
|
||||
|
||||
// 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) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue