diff --git a/examples/buddybook/src/App.tsx b/examples/buddybook/src/App.tsx index 3361086..4921f53 100644 --- a/examples/buddybook/src/App.tsx +++ b/examples/buddybook/src/App.tsx @@ -52,8 +52,14 @@ function App() { if (isWakuLoading) { return ( -
- +
+
+

BuddyBook

+
+ +

Connecting to Waku's decentralized network...

+
+
); } @@ -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() { } /> } /> } /> - } /> + + } + /> } /> } /> diff --git a/examples/buddybook/src/components/Chain/SignSharedChain.tsx b/examples/buddybook/src/components/Chain/SignSharedChain.tsx index a57f6bc..b3eceb9 100644 --- a/examples/buddybook/src/components/Chain/SignSharedChain.tsx +++ b/examples/buddybook/src/components/Chain/SignSharedChain.tsx @@ -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 = ({ chainsData, onChainUpdate }) => { +const SignSharedChain: React.FC = ({ chainsData, onChainUpdate, isLoading }) => { const { chainUUID, blockUUID } = useParams(); const [block, setBlock] = useState(null); const navigate = useNavigate(); @@ -22,6 +24,17 @@ const SignSharedChain: React.FC = ({ chainsData, onChainUp } }, [chainsData, chainUUID, blockUUID]); + if (isLoading && !block) { + return ( + + + +

Looking for chain...

+
+
+ ); + } + if (!block) { return ( diff --git a/examples/buddybook/src/components/Chain/View/ChainList.tsx b/examples/buddybook/src/components/Chain/View/ChainList.tsx index cbdd84e..da40388 100644 --- a/examples/buddybook/src/components/Chain/View/ChainList.tsx +++ b/examples/buddybook/src/components/Chain/View/ChainList.tsx @@ -101,14 +101,18 @@ const ChainList: React.FC = ({ chainsData, onChainUpdate, isLoad return ( - Existing Chains + + Existing Chains + {isLoading && ( + + + Loading more chains... + + )} + - {isLoading ? ( -
- -
- ) : rootBlocks.length === 0 ? ( + {rootBlocks.length === 0 && !isLoading ? (

No chains found.

) : (
    diff --git a/examples/buddybook/src/components/Header.tsx b/examples/buddybook/src/components/Header.tsx index 1d9c093..1fc763a 100644 --- a/examples/buddybook/src/components/Header.tsx +++ b/examples/buddybook/src/components/Header.tsx @@ -93,14 +93,28 @@ const Header: React.FC = ({ wakuStatus }) => {
    -
    - Filter: -
    -
    -
    - Store: -
    -
    + {isWakuLoading ? ( +
    + + Connecting... +
    + ) : wakuError ? ( + Network Error + ) : ( + <> +
    + Filter: +
    +
    +
    + Store: +
    +
    + + {connections > 0 ? `${connections} peer${connections === 1 ? '' : 's'}` : 'Connecting...'} + + + )}
    diff --git a/examples/buddybook/src/lib/waku.ts b/examples/buddybook/src/lib/waku.ts index 43c1e46..24bbb3c 100644 --- a/examples/buddybook/src/lib/waku.ts +++ b/examples/buddybook/src/lib/waku.ts @@ -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) => { - console.log(message) - if (!message.payload) return; - 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); - }) + 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) 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); + yield blockPayload; + } + } console.timeEnd("getMessagesFromStore") - return messages; } export async function subscribeToFilter(node: LightNode, callback: (message: BlockPayload) => void) { diff --git a/examples/buddybook/tasks.md b/examples/buddybook/tasks.md index 538283e..2f988d3 100644 --- a/examples/buddybook/tasks.md +++ b/examples/buddybook/tasks.md @@ -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 \ No newline at end of file +- [ 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 \ No newline at end of file