From c047f204e9bfd409417ca2a1d48351f5e0e1fb6a Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Mon, 11 Nov 2024 18:01:27 +0700 Subject: [PATCH] chore: prepare --- examples/buddybook/index.html | 8 - examples/buddybook/public/404.html | 21 --- examples/buddybook/src/App.tsx | 4 +- .../src/components/Chain/SignChain.tsx | 165 +++++++++--------- .../src/components/Chain/View/ChainList.tsx | 25 +-- examples/buddybook/src/components/QRCode.tsx | 106 ++++++++--- .../buddybook/src/components/ui/dialog.tsx | 10 +- examples/buddybook/src/lib/waku-config.ts | 6 - examples/buddybook/src/lib/waku.ts | 6 +- examples/buddybook/src/main.tsx | 2 +- 10 files changed, 188 insertions(+), 165 deletions(-) delete mode 100644 examples/buddybook/public/404.html delete mode 100644 examples/buddybook/src/lib/waku-config.ts diff --git a/examples/buddybook/index.html b/examples/buddybook/index.html index bd3d433..8a24820 100644 --- a/examples/buddybook/index.html +++ b/examples/buddybook/index.html @@ -23,14 +23,6 @@ browser: true }; -
diff --git a/examples/buddybook/public/404.html b/examples/buddybook/public/404.html deleted file mode 100644 index df98f7b..0000000 --- a/examples/buddybook/public/404.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - BuddyBook - - - - - \ No newline at end of file diff --git a/examples/buddybook/src/App.tsx b/examples/buddybook/src/App.tsx index 3a46233..6392a5a 100644 --- a/examples/buddybook/src/App.tsx +++ b/examples/buddybook/src/App.tsx @@ -41,8 +41,9 @@ function App() { }, []); useEffect(() => { - if (isWakuLoading || !node || node.libp2p.getConnections().length === 0 || chainsData.length > 0 || isListening) return; + if (isWakuLoading || !node || node.libp2p.getConnections().length <= 1 || chainsData.length > 0 || isListening) return; setIsListening(true); + console.log("connections", node.libp2p.getConnections().length) startMessageListening(); }, [node, isWakuLoading, wakuStatus]) @@ -67,6 +68,7 @@ function App() { const startMessageListening = async () => { console.log("Starting message listening") + console.log("connections", node.libp2p.getConnections().length) try { setWakuStatus(prev => ({ ...prev, store: 'in-progress' })); setIsLoadingChains(true); diff --git a/examples/buddybook/src/components/Chain/SignChain.tsx b/examples/buddybook/src/components/Chain/SignChain.tsx index 9547ea6..359e8fb 100644 --- a/examples/buddybook/src/components/Chain/SignChain.tsx +++ b/examples/buddybook/src/components/Chain/SignChain.tsx @@ -9,9 +9,10 @@ import { Loader2 } from "lucide-react"; import QRCode from '@/components/QRCode'; import { useWalletPrompt } from '@/hooks/useWalletPrompt'; import { v4 as uuidv4 } from 'uuid'; + interface SignChainProps { block: BlockPayload; - chainsData: BlockPayload[]; // Add this prop + chainsData: BlockPayload[]; onSuccess: (newBlock: BlockPayload) => void; } @@ -20,43 +21,49 @@ const SignChain: React.FC = ({ block, chainsData, onSuccess }) = const [isSigning, setIsSigning] = useState(false); const [error, setError] = useState(null); const [alreadySigned, setAlreadySigned] = useState(false); + const [isWalletPrompt, setIsWalletPrompt] = useState(false); + const { address } = useAccount(); const { data: ensName } = useEnsName({ address }); const { node } = useWaku(); const { ensureWalletConnected } = useWalletPrompt(); - const [isWalletPrompt, setIsWalletPrompt] = useState(false); + + const checkSignatures = (blockToCheck: BlockPayload, visitedBlocks: Set): boolean => { + if (visitedBlocks.has(blockToCheck.blockUUID)) return false; + visitedBlocks.add(blockToCheck.blockUUID); + + // Check current block signatures + if (blockToCheck.signatures?.some(sig => sig?.address?.toLowerCase() === address?.toLowerCase())) { + return true; + } + + // Check parent block + const parentBlock = chainsData.find(b => b.blockUUID === blockToCheck.parentBlockUUID); + if (parentBlock && checkSignatures(parentBlock, visitedBlocks)) { + return true; + } + + // Check immediate child blocks + return chainsData + .filter(b => b.parentBlockUUID === blockToCheck.blockUUID) + .some(childBlock => checkSignatures(childBlock, visitedBlocks)); + }; useEffect(() => { - if (address) { - // Check if the address has signed this block or any blocks in the chain - const checkSignatures = (blockToCheck: BlockPayload): boolean => { - // Check current block's signatures - if (blockToCheck.signatures.some( - sig => sig.address.toLowerCase() === address.toLowerCase() - )) { - return true; - } + if (!address) return; - // Check parent blocks - const parentBlock = chainsData.find(b => b.blockUUID === blockToCheck.parentBlockUUID); - if (parentBlock && checkSignatures(parentBlock)) { - return true; - } - - // Check child blocks - const childBlocks = chainsData.filter(b => b.parentBlockUUID === blockToCheck.blockUUID); - return childBlocks.some(childBlock => checkSignatures(childBlock)); - }; - - const hasAlreadySigned = checkSignatures(block); - setAlreadySigned(hasAlreadySigned); + try { + const visitedBlocks = new Set(); + setAlreadySigned(checkSignatures(block, visitedBlocks)); + } catch (error) { + console.error('Error in signature check:', error); + setAlreadySigned(false); } }, [address, block, chainsData]); const { signMessage } = useSignMessage({ mutation: { onMutate() { - // Reset any previous errors when starting a new signing attempt setError(null); setIsSigning(true); }, @@ -64,7 +71,6 @@ const SignChain: React.FC = ({ block, chainsData, onSuccess }) = if (!address || !node) return; try { - // Double check signature before proceeding if (block.signatures.some(sig => sig.address.toLowerCase() === address.toLowerCase())) { setError('You have already signed this chain.'); return; @@ -108,17 +114,14 @@ const SignChain: React.FC = ({ block, chainsData, onSuccess }) = const handleSign = async () => { try { if (!address) { - // If not connected, try to connect first setIsWalletPrompt(true); const connected = await ensureWalletConnected(); - setIsWalletPrompt(false); if (!connected) { setError('Please ensure your wallet is connected and the app is open.'); return; } } - // Check if already signed if (alreadySigned) { setError('You have already signed this chain.'); return; @@ -131,17 +134,17 @@ const SignChain: React.FC = ({ block, chainsData, onSuccess }) = return; } - // Prepare the message - const message = `Sign Block: -Chain UUID: ${block.chainUUID} -Block UUID: ${block.blockUUID} -Title: ${block.title} -Description: ${block.description} -Timestamp: ${new Date().getTime()} -Parent Block UUID: ${block.parentBlockUUID} -Signed by: ${ensName || address}`; + const message = [ + 'Sign Block:', + `Chain UUID: ${block.chainUUID}`, + `Block UUID: ${block.blockUUID}`, + `Title: ${block.title}`, + `Description: ${block.description}`, + `Timestamp: ${new Date().getTime()}`, + `Parent Block UUID: ${block.parentBlockUUID}`, + `Signed by: ${ensName || address}` + ].join('\n'); - // Trigger signing signMessage({ message }); } catch (error) { console.error('Error in sign flow:', error); @@ -152,14 +155,24 @@ Signed by: ${ensName || address}`; } }; + const getButtonText = () => { + if (isSigning) return 'Signing...'; + if (isWalletPrompt) return 'Connecting...'; + if (alreadySigned) return 'Already Signed'; + if (!address) return 'Connect Wallet'; + return 'Sign'; + }; + + const showLoadingSpinner = isSigning || isWalletPrompt; + return ( <> - - + + Sign Chain {alreadySigned @@ -167,57 +180,39 @@ Signed by: ${ensName || address}`; : 'Review the block details and sign to add your signature to the chain.'} -
-
-

Block Details

-

{block.title}

-

{block.description}

+
+
+
+

Block Details

+

{block.title}

+

{block.description}

+
+
+ +
- + {(error || isWalletPrompt) && ( +
+ {error &&

{error}

} + {isWalletPrompt && ( +
+

Attempting to connect to your wallet...

+

+ If your wallet doesn't open automatically, please open it manually to approve the connection. +

+
+ )} +
+ )}
- {(error || isWalletPrompt) && ( -
- {error &&

{error}

} - {isWalletPrompt && ( -
-

- Attempting to connect to your wallet... -

-

- If your wallet doesn't open automatically, please open it manually to approve the connection. -

-
- )} - {/iPhone|iPad|iPod|Android/i.test(navigator.userAgent) && ( -

- Tip: If your wallet doesn't open automatically, minimize this app and open your wallet manually before trying again. -

- )} -
- )} - + diff --git a/examples/buddybook/src/components/Chain/View/ChainList.tsx b/examples/buddybook/src/components/Chain/View/ChainList.tsx index 2a0369b..2b9d6aa 100644 --- a/examples/buddybook/src/components/Chain/View/ChainList.tsx +++ b/examples/buddybook/src/components/Chain/View/ChainList.tsx @@ -4,7 +4,7 @@ import { type BlockPayload } from '@/lib/waku'; import SignChain from '@/components/Chain/SignChain'; import { useEnsName } from 'wagmi'; import { Button } from '@/components/ui/button'; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogDescription } from "@/components/ui/dialog"; +import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger, DialogDescription, DialogFooter } from "@/components/ui/dialog"; import QRCode from '@/components/QRCode'; import { Loader2 } from "lucide-react"; @@ -64,22 +64,23 @@ const ChainList: React.FC = ({ chainsData, onChainUpdate, isLoad - + - Share this Chain + Share Chain Share this chain with others to collect their signatures. -
- -

{shareUrl}

- + +
+
diff --git a/examples/buddybook/src/components/QRCode.tsx b/examples/buddybook/src/components/QRCode.tsx index 889f6d5..98c3974 100644 --- a/examples/buddybook/src/components/QRCode.tsx +++ b/examples/buddybook/src/components/QRCode.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; import { QRCodeSVG } from 'qrcode.react'; import { Button } from "@/components/ui/button"; import { Check, Copy } from "lucide-react"; @@ -7,11 +7,37 @@ interface QRCodeProps { text: string; width?: number; height?: number; + showCopyButton?: 'icon' | 'text' | 'both'; + title?: string; + description?: string; } -const QRCode: React.FC = ({ text, width = 256, height = 256 }) => { +const QRCode: React.FC = ({ + text, + width = 256, + height = 256, + showCopyButton = 'both', + title, + description +}) => { const [copied, setCopied] = useState(false); - const isMobile = window.innerWidth < 640; + const [isMobile, setIsMobile] = useState(false); + const [qrSize, setQrSize] = useState(Math.min(width, height)); + + useEffect(() => { + const checkMobile = () => { + setIsMobile(window.innerWidth < 640); + setQrSize( + window.innerWidth < 640 + ? Math.min(window.innerWidth - 80, 200) + : Math.min(width, height) + ); + }; + + checkMobile(); + window.addEventListener('resize', checkMobile); + return () => window.removeEventListener('resize', checkMobile); + }, [width, height]); const handleCopy = async () => { await navigator.clipboard.writeText(text); @@ -19,28 +45,66 @@ const QRCode: React.FC = ({ text, width = 256, height = 256 }) => { setTimeout(() => setCopied(false), 2000); }; + const handleShare = async () => { + if (navigator.share) { + try { + await navigator.share({ + title: title || 'Share Chain', + text: description || 'Sign this chain', + url: text + }); + } catch (error) { + if (error instanceof Error && error.name !== 'AbortError') { + console.error('Error sharing:', error); + } + } + } else { + handleCopy(); + } + }; + return ( -
- -
- +
+ -
+ + {showCopyButton !== 'text' && ( +
+ + +
+ )} + + {showCopyButton === 'text' && ( + + )}
); }; diff --git a/examples/buddybook/src/components/ui/dialog.tsx b/examples/buddybook/src/components/ui/dialog.tsx index 0e36c68..0946c1b 100644 --- a/examples/buddybook/src/components/ui/dialog.tsx +++ b/examples/buddybook/src/components/ui/dialog.tsx @@ -35,14 +35,12 @@ const DialogContent = React.forwardRef<