chore(buddybook): enhancements (#105)
This commit is contained in:
parent
b0f2547732
commit
6ac81de93c
|
@ -52,8 +52,14 @@ function App() {
|
|||
|
||||
if (isWakuLoading) {
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground flex justify-center items-center">
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
<div className="container mx-auto px-4 py-16 flex flex-col items-center justify-center space-y-4">
|
||||
<h1 className="text-2xl md:text-4xl font-bold">BuddyBook</h1>
|
||||
<div className="flex flex-col items-center space-y-2">
|
||||
<Loader2 className="h-8 w-8 animate-spin" />
|
||||
<p className="text-muted-foreground">Connecting to Waku's decentralized network...</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -63,8 +69,17 @@ function App() {
|
|||
try {
|
||||
setWakuStatus(prev => ({ ...prev, store: 'in-progress' }));
|
||||
setIsLoadingChains(true);
|
||||
const storeMessages = await getMessagesFromStore(node as LightNode)
|
||||
setChainsData(storeMessages)
|
||||
const messageGenerator = getMessagesFromStore(node as LightNode);
|
||||
|
||||
// Process messages as they arrive
|
||||
for await (const message of messageGenerator) {
|
||||
setChainsData(prevChains => {
|
||||
const blockExists = prevChains.some(block => block.blockUUID === message.blockUUID);
|
||||
if (blockExists) return prevChains;
|
||||
return [...prevChains, message];
|
||||
});
|
||||
}
|
||||
|
||||
setWakuStatus(prev => ({ ...prev, store: 'success' }));
|
||||
} catch (error) {
|
||||
console.error("Error fetching messages from store:", error);
|
||||
|
@ -117,7 +132,16 @@ function App() {
|
|||
<Route path="/create" element={<ChainCreationForm />} />
|
||||
<Route path="/view" element={<ChainList chainsData={chainsData} onChainUpdate={handleChainUpdate} isLoading={isLoadingChains} />} />
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/sign/:chainUUID/:blockUUID" element={<SignSharedChain chainsData={chainsData} onChainUpdate={handleChainUpdate} />} />
|
||||
<Route
|
||||
path="/sign/:chainUUID/:blockUUID"
|
||||
element={
|
||||
<SignSharedChain
|
||||
chainsData={chainsData}
|
||||
onChainUpdate={handleChainUpdate}
|
||||
isLoading={isLoadingChains}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<Route path="/telemetry" element={<TelemetryPage />} />
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
|
|
|
@ -4,13 +4,15 @@ import { BlockPayload } from '@/lib/waku';
|
|||
import SignChain from './SignChain';
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Loader2 } from "lucide-react";
|
||||
|
||||
interface SignSharedChainProps {
|
||||
chainsData: BlockPayload[];
|
||||
onChainUpdate: (newBlock: BlockPayload) => void;
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
const SignSharedChain: React.FC<SignSharedChainProps> = ({ chainsData, onChainUpdate }) => {
|
||||
const SignSharedChain: React.FC<SignSharedChainProps> = ({ chainsData, onChainUpdate, isLoading }) => {
|
||||
const { chainUUID, blockUUID } = useParams();
|
||||
const [block, setBlock] = useState<BlockPayload | null>(null);
|
||||
const navigate = useNavigate();
|
||||
|
@ -22,6 +24,17 @@ const SignSharedChain: React.FC<SignSharedChainProps> = ({ chainsData, onChainUp
|
|||
}
|
||||
}, [chainsData, chainUUID, blockUUID]);
|
||||
|
||||
if (isLoading && !block) {
|
||||
return (
|
||||
<Card className="w-full max-w-md mx-auto">
|
||||
<CardContent className="flex flex-col items-center justify-center py-8 space-y-4">
|
||||
<Loader2 className="h-8 w-8 animate-spin" />
|
||||
<p className="text-sm text-muted-foreground">Looking for chain...</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
if (!block) {
|
||||
return (
|
||||
<Card className="w-full max-w-md mx-auto">
|
||||
|
|
|
@ -101,14 +101,18 @@ const ChainList: React.FC<ChainListProps> = ({ chainsData, onChainUpdate, isLoad
|
|||
return (
|
||||
<Card className="w-full max-w-4xl mx-auto">
|
||||
<CardHeader>
|
||||
<CardTitle>Existing Chains</CardTitle>
|
||||
<CardTitle>
|
||||
Existing Chains
|
||||
{isLoading && (
|
||||
<span className="ml-2 inline-flex items-center text-muted-foreground text-sm font-normal">
|
||||
<Loader2 className="h-4 w-4 animate-spin mr-2" />
|
||||
Loading more chains...
|
||||
</span>
|
||||
)}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{isLoading ? (
|
||||
<div className="flex justify-center items-center h-32">
|
||||
<Loader2 className="h-8 w-8 animate-spin" />
|
||||
</div>
|
||||
) : rootBlocks.length === 0 ? (
|
||||
{rootBlocks.length === 0 && !isLoading ? (
|
||||
<p>No chains found.</p>
|
||||
) : (
|
||||
<ul className="space-y-4">
|
||||
|
|
|
@ -93,6 +93,15 @@ const Header: React.FC<HeaderProps> = ({ wakuStatus }) => {
|
|||
|
||||
<div className="flex flex-wrap justify-center md:justify-end items-center gap-2 w-full md:w-auto">
|
||||
<div className="flex items-center space-x-2 text-xs md:text-sm">
|
||||
{isWakuLoading ? (
|
||||
<div className="flex items-center space-x-2">
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
<span className="text-muted-foreground">Connecting...</span>
|
||||
</div>
|
||||
) : wakuError ? (
|
||||
<span className="text-destructive">Network Error</span>
|
||||
) : (
|
||||
<>
|
||||
<div className="flex items-center space-x-1">
|
||||
<span className="text-muted-foreground">Filter:</span>
|
||||
<div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${getStatusColor(wakuStatus.filter)}`}></div>
|
||||
|
@ -101,6 +110,11 @@ const Header: React.FC<HeaderProps> = ({ wakuStatus }) => {
|
|||
<span className="text-muted-foreground">Store:</span>
|
||||
<div className={`w-2 h-2 md:w-3 md:h-3 rounded-full ${getStatusColor(wakuStatus.store)}`}></div>
|
||||
</div>
|
||||
<span className="text-xs md:text-sm text-muted-foreground hidden md:inline">
|
||||
{connections > 0 ? `${connections} peer${connections === 1 ? '' : 's'}` : 'Connecting...'}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2">
|
||||
|
|
|
@ -65,18 +65,19 @@ export function createMessage({
|
|||
return { payload: payload };
|
||||
}
|
||||
|
||||
export async function getMessagesFromStore(node: LightNode) {
|
||||
export async function* getMessagesFromStore(node: LightNode) {
|
||||
console.time("getMessagesFromStore")
|
||||
const messages: BlockPayload[] = [];
|
||||
await node.store.queryWithOrderedCallback([decoder], async (message) => {
|
||||
for await (const messagePromises of node.store.queryGenerator([decoder])) {
|
||||
const messages = await Promise.all(messagePromises);
|
||||
for (const message of messages) {
|
||||
console.log(message)
|
||||
if (!message.payload) return;
|
||||
if (!message?.payload) continue;
|
||||
const blockPayload = block.decode(message.payload) as unknown as BlockPayload;
|
||||
blockPayload.signatures = blockPayload.signatures.map(s => JSON.parse(s as unknown as string) as Signature);
|
||||
messages.push(blockPayload);
|
||||
})
|
||||
yield blockPayload;
|
||||
}
|
||||
}
|
||||
console.timeEnd("getMessagesFromStore")
|
||||
return messages;
|
||||
}
|
||||
|
||||
export async function subscribeToFilter(node: LightNode, callback: (message: BlockPayload) => void) {
|
||||
|
|
|
@ -7,5 +7,6 @@
|
|||
- [ ] landing page
|
||||
- [ ] look into high initial loading times
|
||||
- [ ] fix deployment/hosting
|
||||
- [ ] sign shared chain route should show spinner while waiting for the store query to resolve
|
||||
- [ ] create chain -> QR modal should have a sharable link instead of the object
|
||||
- [ x ] sign shared chain route should show spinner while waiting for the store query to resolve
|
||||
- [ x ] create chain -> QR modal should have a sharable link instead of the object
|
||||
- [ x ] store query should yield messages as they come in, instead of waiting for all of them to come in before displaying anything
|
Loading…
Reference in New Issue