mirror of
https://github.com/waku-org/js-waku-lab.git
synced 2025-03-04 02:20:40 +00:00
chore: prepare
This commit is contained in:
parent
da8b9c9790
commit
c047f204e9
@ -23,14 +23,6 @@
|
|||||||
browser: true
|
browser: true
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript">
|
|
||||||
(function() {
|
|
||||||
const path = window.location.pathname;
|
|
||||||
if (path && !window.location.search.includes('?/')) {
|
|
||||||
window.location.replace('/?/' + path + window.location.search + window.location.hash);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>BuddyBook</title>
|
|
||||||
<script type="text/javascript">
|
|
||||||
var pathSegmentsToKeep = 0;
|
|
||||||
|
|
||||||
var l = window.location;
|
|
||||||
l.replace(
|
|
||||||
l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') +
|
|
||||||
'/?/' +
|
|
||||||
l.pathname.slice(1).split('/').slice(pathSegmentsToKeep).join('/').replace(/&/g, '~and~') +
|
|
||||||
(l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') +
|
|
||||||
l.hash
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -41,8 +41,9 @@ function App() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
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);
|
setIsListening(true);
|
||||||
|
console.log("connections", node.libp2p.getConnections().length)
|
||||||
startMessageListening();
|
startMessageListening();
|
||||||
}, [node, isWakuLoading, wakuStatus])
|
}, [node, isWakuLoading, wakuStatus])
|
||||||
|
|
||||||
@ -67,6 +68,7 @@ function App() {
|
|||||||
|
|
||||||
const startMessageListening = async () => {
|
const startMessageListening = async () => {
|
||||||
console.log("Starting message listening")
|
console.log("Starting message listening")
|
||||||
|
console.log("connections", node.libp2p.getConnections().length)
|
||||||
try {
|
try {
|
||||||
setWakuStatus(prev => ({ ...prev, store: 'in-progress' }));
|
setWakuStatus(prev => ({ ...prev, store: 'in-progress' }));
|
||||||
setIsLoadingChains(true);
|
setIsLoadingChains(true);
|
||||||
|
@ -9,9 +9,10 @@ import { Loader2 } from "lucide-react";
|
|||||||
import QRCode from '@/components/QRCode';
|
import QRCode from '@/components/QRCode';
|
||||||
import { useWalletPrompt } from '@/hooks/useWalletPrompt';
|
import { useWalletPrompt } from '@/hooks/useWalletPrompt';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
interface SignChainProps {
|
interface SignChainProps {
|
||||||
block: BlockPayload;
|
block: BlockPayload;
|
||||||
chainsData: BlockPayload[]; // Add this prop
|
chainsData: BlockPayload[];
|
||||||
onSuccess: (newBlock: BlockPayload) => void;
|
onSuccess: (newBlock: BlockPayload) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,43 +21,49 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||||||
const [isSigning, setIsSigning] = useState(false);
|
const [isSigning, setIsSigning] = useState(false);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const [alreadySigned, setAlreadySigned] = useState(false);
|
const [alreadySigned, setAlreadySigned] = useState(false);
|
||||||
|
const [isWalletPrompt, setIsWalletPrompt] = useState(false);
|
||||||
|
|
||||||
const { address } = useAccount();
|
const { address } = useAccount();
|
||||||
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);
|
|
||||||
|
const checkSignatures = (blockToCheck: BlockPayload, visitedBlocks: Set<string>): 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(() => {
|
useEffect(() => {
|
||||||
if (address) {
|
if (!address) return;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check parent blocks
|
try {
|
||||||
const parentBlock = chainsData.find(b => b.blockUUID === blockToCheck.parentBlockUUID);
|
const visitedBlocks = new Set<string>();
|
||||||
if (parentBlock && checkSignatures(parentBlock)) {
|
setAlreadySigned(checkSignatures(block, visitedBlocks));
|
||||||
return true;
|
} catch (error) {
|
||||||
}
|
console.error('Error in signature check:', error);
|
||||||
|
setAlreadySigned(false);
|
||||||
// Check child blocks
|
|
||||||
const childBlocks = chainsData.filter(b => b.parentBlockUUID === blockToCheck.blockUUID);
|
|
||||||
return childBlocks.some(childBlock => checkSignatures(childBlock));
|
|
||||||
};
|
|
||||||
|
|
||||||
const hasAlreadySigned = checkSignatures(block);
|
|
||||||
setAlreadySigned(hasAlreadySigned);
|
|
||||||
}
|
}
|
||||||
}, [address, block, chainsData]);
|
}, [address, block, chainsData]);
|
||||||
|
|
||||||
const { signMessage } = useSignMessage({
|
const { signMessage } = useSignMessage({
|
||||||
mutation: {
|
mutation: {
|
||||||
onMutate() {
|
onMutate() {
|
||||||
// Reset any previous errors when starting a new signing attempt
|
|
||||||
setError(null);
|
setError(null);
|
||||||
setIsSigning(true);
|
setIsSigning(true);
|
||||||
},
|
},
|
||||||
@ -64,7 +71,6 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||||||
if (!address || !node) return;
|
if (!address || !node) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Double check signature before proceeding
|
|
||||||
if (block.signatures.some(sig => sig.address.toLowerCase() === address.toLowerCase())) {
|
if (block.signatures.some(sig => sig.address.toLowerCase() === address.toLowerCase())) {
|
||||||
setError('You have already signed this chain.');
|
setError('You have already signed this chain.');
|
||||||
return;
|
return;
|
||||||
@ -108,17 +114,14 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||||||
const handleSign = async () => {
|
const handleSign = async () => {
|
||||||
try {
|
try {
|
||||||
if (!address) {
|
if (!address) {
|
||||||
// If not connected, try to connect first
|
|
||||||
setIsWalletPrompt(true);
|
setIsWalletPrompt(true);
|
||||||
const connected = await ensureWalletConnected();
|
const connected = await ensureWalletConnected();
|
||||||
setIsWalletPrompt(false);
|
|
||||||
if (!connected) {
|
if (!connected) {
|
||||||
setError('Please ensure your wallet is connected and the app is open.');
|
setError('Please ensure your wallet is connected and the app is open.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if already signed
|
|
||||||
if (alreadySigned) {
|
if (alreadySigned) {
|
||||||
setError('You have already signed this chain.');
|
setError('You have already signed this chain.');
|
||||||
return;
|
return;
|
||||||
@ -131,17 +134,17 @@ const SignChain: React.FC<SignChainProps> = ({ block, chainsData, onSuccess }) =
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the message
|
const message = [
|
||||||
const message = `Sign Block:
|
'Sign Block:',
|
||||||
Chain UUID: ${block.chainUUID}
|
`Chain UUID: ${block.chainUUID}`,
|
||||||
Block UUID: ${block.blockUUID}
|
`Block UUID: ${block.blockUUID}`,
|
||||||
Title: ${block.title}
|
`Title: ${block.title}`,
|
||||||
Description: ${block.description}
|
`Description: ${block.description}`,
|
||||||
Timestamp: ${new Date().getTime()}
|
`Timestamp: ${new Date().getTime()}`,
|
||||||
Parent Block UUID: ${block.parentBlockUUID}
|
`Parent Block UUID: ${block.parentBlockUUID}`,
|
||||||
Signed by: ${ensName || address}`;
|
`Signed by: ${ensName || address}`
|
||||||
|
].join('\n');
|
||||||
|
|
||||||
// Trigger signing
|
|
||||||
signMessage({ message });
|
signMessage({ message });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error in sign flow:', 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 (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button onClick={() => setIsOpen(true)} disabled={alreadySigned}>
|
<Button onClick={() => setIsOpen(true)} disabled={alreadySigned}>
|
||||||
{alreadySigned ? 'Already Signed' : !address ? 'Connect Wallet' : 'Sign Chain'}
|
{alreadySigned ? 'Already Signed' : !address ? 'Connect Wallet' : 'Sign Chain'}
|
||||||
</Button>
|
</Button>
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogContent className="sm:max-w-md">
|
<DialogContent className="sm:max-w-md flex flex-col max-h-[90vh] md:max-h-[85vh]">
|
||||||
<DialogHeader>
|
<DialogHeader className="flex-shrink-0">
|
||||||
<DialogTitle>Sign Chain</DialogTitle>
|
<DialogTitle>Sign Chain</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
{alreadySigned
|
{alreadySigned
|
||||||
@ -167,57 +180,39 @@ Signed by: ${ensName || address}`;
|
|||||||
: 'Review the block details and sign to add your signature to the chain.'}
|
: 'Review the block details and sign to add your signature to the chain.'}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="flex flex-col space-y-4">
|
<div className="flex-1 min-h-0 overflow-y-auto py-4">
|
||||||
<div className="space-y-2">
|
<div className="space-y-4">
|
||||||
<h4 className="font-medium">Block Details</h4>
|
<div className="space-y-2">
|
||||||
<p className="text-sm text-muted-foreground">{block.title}</p>
|
<h4 className="font-medium">Block Details</h4>
|
||||||
<p className="text-sm text-muted-foreground">{block.description}</p>
|
<p className="text-sm text-muted-foreground">{block.title}</p>
|
||||||
|
<p className="text-sm text-muted-foreground">{block.description}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-center">
|
||||||
|
<QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<QRCode text={`${window.location.origin}/sign/${block.chainUUID}/${block.blockUUID}`} />
|
{(error || isWalletPrompt) && (
|
||||||
|
<div className="space-y-2 mt-4">
|
||||||
|
{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>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{(error || isWalletPrompt) && (
|
<DialogFooter className="flex-shrink-0 mt-4">
|
||||||
<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 variant="secondary" onClick={() => setIsOpen(false)}>Cancel</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={handleSign}
|
onClick={handleSign}
|
||||||
disabled={isSigning || alreadySigned || isWalletPrompt}
|
disabled={isSigning || alreadySigned || isWalletPrompt}
|
||||||
>
|
>
|
||||||
{isSigning ? (
|
{showLoadingSpinner && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||||
<>
|
{getButtonText()}
|
||||||
<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 ? (
|
|
||||||
'Connect Wallet'
|
|
||||||
) : (
|
|
||||||
'Sign'
|
|
||||||
)}
|
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
@ -4,7 +4,7 @@ import { type BlockPayload } from '@/lib/waku';
|
|||||||
import SignChain from '@/components/Chain/SignChain';
|
import SignChain from '@/components/Chain/SignChain';
|
||||||
import { useEnsName } from 'wagmi';
|
import { useEnsName } from 'wagmi';
|
||||||
import { Button } from '@/components/ui/button';
|
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 QRCode from '@/components/QRCode';
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
|
|
||||||
@ -64,22 +64,23 @@ const ChainList: React.FC<ChainListProps> = ({ chainsData, onChainUpdate, isLoad
|
|||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="outline">Share</Button>
|
<Button variant="outline">Share</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
<DialogContent className="sm:max-w-md">
|
<DialogContent className="flex flex-col gap-4">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>Share this Chain</DialogTitle>
|
<DialogTitle>Share Chain</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Share this chain with others to collect their signatures.
|
Share this chain with others to collect their signatures.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
|
||||||
<QRCode text={shareUrl} width={200} height={200} />
|
<div className="flex flex-col items-center gap-4">
|
||||||
<p className="text-sm text-center break-all">{shareUrl}</p>
|
<QRCode
|
||||||
<Button
|
text={shareUrl}
|
||||||
onClick={() => navigator.clipboard.writeText(shareUrl)}
|
width={180}
|
||||||
variant="outline"
|
height={180}
|
||||||
>
|
showCopyButton="text"
|
||||||
Copy Link
|
title={block.title}
|
||||||
</Button>
|
description={`Sign this chain: ${block.title}`}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { QRCodeSVG } from 'qrcode.react';
|
import { QRCodeSVG } from 'qrcode.react';
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Check, Copy } from "lucide-react";
|
import { Check, Copy } from "lucide-react";
|
||||||
@ -7,11 +7,37 @@ interface QRCodeProps {
|
|||||||
text: string;
|
text: string;
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
showCopyButton?: 'icon' | 'text' | 'both';
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QRCode: React.FC<QRCodeProps> = ({ text, width = 256, height = 256 }) => {
|
const QRCode: React.FC<QRCodeProps> = ({
|
||||||
|
text,
|
||||||
|
width = 256,
|
||||||
|
height = 256,
|
||||||
|
showCopyButton = 'both',
|
||||||
|
title,
|
||||||
|
description
|
||||||
|
}) => {
|
||||||
const [copied, setCopied] = useState(false);
|
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 () => {
|
const handleCopy = async () => {
|
||||||
await navigator.clipboard.writeText(text);
|
await navigator.clipboard.writeText(text);
|
||||||
@ -19,28 +45,66 @@ const QRCode: React.FC<QRCodeProps> = ({ text, width = 256, height = 256 }) => {
|
|||||||
setTimeout(() => setCopied(false), 2000);
|
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 (
|
return (
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center w-full space-y-4">
|
||||||
<QRCodeSVG
|
<div className="flex justify-center w-full">
|
||||||
value={text}
|
<QRCodeSVG
|
||||||
size={isMobile ? Math.min(width * 0.8, window.innerWidth - 64) : Math.min(width, height)}
|
|
||||||
/>
|
|
||||||
<div className="flex items-center space-x-2 w-full max-w-[300px]">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
value={text}
|
value={text}
|
||||||
readOnly
|
size={qrSize}
|
||||||
className="flex-1 px-3 py-2 text-xs sm:text-sm border rounded-md bg-muted truncate"
|
className="max-w-full"
|
||||||
/>
|
/>
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
size="icon"
|
|
||||||
onClick={handleCopy}
|
|
||||||
className="shrink-0"
|
|
||||||
>
|
|
||||||
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{showCopyButton !== 'text' && (
|
||||||
|
<div className="flex items-center space-x-2 w-full">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={text}
|
||||||
|
readOnly
|
||||||
|
className="flex-1 px-3 py-2 text-xs sm:text-sm border rounded-md bg-muted truncate"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
onClick={handleCopy}
|
||||||
|
className="shrink-0"
|
||||||
|
>
|
||||||
|
{copied ? <Check className="h-4 w-4" /> : <Copy className="h-4 w-4" />}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{showCopyButton === 'text' && (
|
||||||
|
<Button
|
||||||
|
onClick={isMobile && 'share' in navigator ? handleShare : handleCopy}
|
||||||
|
variant="secondary"
|
||||||
|
className="w-full sm:w-auto"
|
||||||
|
>
|
||||||
|
{isMobile && 'share' in navigator
|
||||||
|
? 'Share'
|
||||||
|
: copied
|
||||||
|
? 'Copied!'
|
||||||
|
: 'Copy Link'}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -35,14 +35,12 @@ const DialogContent = React.forwardRef<
|
|||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed left-[50%] top-[50%] z-50 grid w-full translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background shadow-lg duration-200",
|
"fixed z-50 border bg-background shadow-lg duration-200",
|
||||||
"p-4 md:p-6",
|
"p-4 md:p-6",
|
||||||
"rounded-t-lg md:rounded-lg",
|
"w-full md:w-[calc(100%-2rem)] md:max-w-lg",
|
||||||
"max-h-[95vh] md:max-h-[85vh]",
|
|
||||||
"w-full md:max-w-lg",
|
|
||||||
"bottom-0 md:bottom-auto",
|
|
||||||
"overflow-y-auto",
|
|
||||||
"focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
"focus:outline-none focus-visible:ring-2 focus-visible:ring-accent",
|
||||||
|
"bottom-0 rounded-t-lg md:rounded-lg",
|
||||||
|
"md:left-[50%] md:top-[50%] md:translate-x-[-50%] md:translate-y-[-50%]",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
import { Protocols } from '@waku/sdk';
|
|
||||||
|
|
||||||
export const WAKU_NODE_OPTIONS = {
|
|
||||||
defaultBootstrap: true,
|
|
||||||
protocols: [Protocols.Store, Protocols.Filter, Protocols.LightPush]
|
|
||||||
};
|
|
@ -1,9 +1,7 @@
|
|||||||
import { createEncoder, createDecoder, type LightNode, type CreateWakuNodeOptions } from "@waku/sdk";
|
import { createEncoder, createDecoder, type LightNode, type CreateWakuNodeOptions } from "@waku/sdk";
|
||||||
import protobuf from 'protobufjs';
|
import protobuf from 'protobufjs';
|
||||||
|
|
||||||
export const WAKU_NODE_OPTIONS: CreateWakuNodeOptions = { defaultBootstrap: true, nodeToUse: {
|
export const WAKU_NODE_OPTIONS: CreateWakuNodeOptions = { defaultBootstrap: true };
|
||||||
store: "/dns4/store-02.ac-cn-hongkong-c.status.staging.status.im/tcp/443/wss/p2p/16Uiu2HAmU7xtcwytXpGpeDrfyhJkiFvTkQbLB9upL5MXPLGceG9K"
|
|
||||||
} };
|
|
||||||
|
|
||||||
|
|
||||||
export type Signature = {
|
export type Signature = {
|
||||||
@ -22,7 +20,7 @@ export type BlockPayload = {
|
|||||||
parentBlockUUID: string | null;
|
parentBlockUUID: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const contentTopic = "/buddybook-dogfood/1/chain/proto";
|
const contentTopic = "/buddybook-devcon/1/chain/proto";
|
||||||
|
|
||||||
export const encoder = createEncoder({
|
export const encoder = createEncoder({
|
||||||
contentTopic: contentTopic,
|
contentTopic: contentTopic,
|
||||||
|
@ -9,7 +9,7 @@ import App from './App.tsx'
|
|||||||
import './index.css'
|
import './index.css'
|
||||||
import { LightNodeProvider } from "@waku/react";
|
import { LightNodeProvider } from "@waku/react";
|
||||||
import { config } from './lib/walletConnect.ts'
|
import { config } from './lib/walletConnect.ts'
|
||||||
import { WAKU_NODE_OPTIONS } from './lib/waku-config.ts'
|
import { WAKU_NODE_OPTIONS } from './lib/waku.ts'
|
||||||
|
|
||||||
// Polyfills
|
// Polyfills
|
||||||
if (typeof global === 'undefined') {
|
if (typeof global === 'undefined') {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user