From 003e890a2a125bf744f99cb77c28e92413a5fa42 Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Tue, 29 Oct 2024 15:22:15 +0530 Subject: [PATCH 1/4] chore: show spinner while chain is loading --- examples/buddybook/src/App.tsx | 11 ++++++++++- .../src/components/Chain/SignSharedChain.tsx | 14 +++++++++++++- examples/buddybook/tasks.md | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/examples/buddybook/src/App.tsx b/examples/buddybook/src/App.tsx index 3361086..b6b30ee 100644 --- a/examples/buddybook/src/App.tsx +++ b/examples/buddybook/src/App.tsx @@ -117,7 +117,16 @@ function App() { } /> } /> } /> - } /> + + } + /> } /> } /> diff --git a/examples/buddybook/src/components/Chain/SignSharedChain.tsx b/examples/buddybook/src/components/Chain/SignSharedChain.tsx index a57f6bc..459de77 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,16 @@ const SignSharedChain: React.FC = ({ chainsData, onChainUp } }, [chainsData, chainUUID, blockUUID]); + if (isLoading) { + return ( + + + + + + ); + } + if (!block) { return ( diff --git a/examples/buddybook/tasks.md b/examples/buddybook/tasks.md index 538283e..06df540 100644 --- a/examples/buddybook/tasks.md +++ b/examples/buddybook/tasks.md @@ -8,4 +8,4 @@ - [ ] 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 ] create chain -> QR modal should have a sharable link instead of the object \ No newline at end of file From 0a2445c3746246f43733161d7e03db35c4b6a3d2 Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Tue, 29 Oct 2024 15:25:15 +0530 Subject: [PATCH 2/4] chore: improve loading screens --- examples/buddybook/src/App.tsx | 10 +++++-- .../src/components/Chain/View/ChainList.tsx | 22 ++++++++++---- examples/buddybook/src/components/Header.tsx | 30 ++++++++++++++----- examples/buddybook/tasks.md | 2 +- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/examples/buddybook/src/App.tsx b/examples/buddybook/src/App.tsx index b6b30ee..92bb746 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...

+
+
); } diff --git a/examples/buddybook/src/components/Chain/View/ChainList.tsx b/examples/buddybook/src/components/Chain/View/ChainList.tsx index cbdd84e..9f80e24 100644 --- a/examples/buddybook/src/components/Chain/View/ChainList.tsx +++ b/examples/buddybook/src/components/Chain/View/ChainList.tsx @@ -98,17 +98,29 @@ const ChainList: React.FC = ({ chainsData, onChainUpdate, isLoad const rootBlocks = chainsData.filter(block => !block.parentBlockUUID); + if (isLoading) { + return ( + + + Loading Chains + + +
+ +

Fetching chains from the network...

+
+
+
+ ); + } + return ( Existing Chains - {isLoading ? ( -
- -
- ) : rootBlocks.length === 0 ? ( + {rootBlocks.length === 0 ? (

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/tasks.md b/examples/buddybook/tasks.md index 06df540..2201860 100644 --- a/examples/buddybook/tasks.md +++ b/examples/buddybook/tasks.md @@ -7,5 +7,5 @@ - [ ] 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 +- [ 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 \ No newline at end of file From 685890f090057445c7d006c4434f751df1fa5a8e Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Tue, 29 Oct 2024 15:35:03 +0530 Subject: [PATCH 3/4] chore: use async generator for store queries to improve load times --- examples/buddybook/src/App.tsx | 13 +++++++-- .../src/components/Chain/View/ChainList.tsx | 28 +++++++------------ examples/buddybook/src/lib/waku.ts | 21 +++++++------- examples/buddybook/tasks.md | 3 +- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/examples/buddybook/src/App.tsx b/examples/buddybook/src/App.tsx index 92bb746..4921f53 100644 --- a/examples/buddybook/src/App.tsx +++ b/examples/buddybook/src/App.tsx @@ -69,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); diff --git a/examples/buddybook/src/components/Chain/View/ChainList.tsx b/examples/buddybook/src/components/Chain/View/ChainList.tsx index 9f80e24..da40388 100644 --- a/examples/buddybook/src/components/Chain/View/ChainList.tsx +++ b/examples/buddybook/src/components/Chain/View/ChainList.tsx @@ -98,29 +98,21 @@ const ChainList: React.FC = ({ chainsData, onChainUpdate, isLoad const rootBlocks = chainsData.filter(block => !block.parentBlockUUID); - if (isLoading) { - return ( - - - Loading Chains - - -
    - -

    Fetching chains from the network...

    -
    -
    -
    - ); - } - return ( - Existing Chains + + Existing Chains + {isLoading && ( + + + Loading more chains... + + )} + - {rootBlocks.length === 0 ? ( + {rootBlocks.length === 0 && !isLoading ? (

    No chains found.

    ) : (
      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 2201860..2f988d3 100644 --- a/examples/buddybook/tasks.md +++ b/examples/buddybook/tasks.md @@ -8,4 +8,5 @@ - [ ] look into high initial loading times - [ ] fix deployment/hosting - [ 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 \ No newline at end of file +- [ 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 From 747f7a3a47678a7bcea62f9faba5b39396f5af27 Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Tue, 29 Oct 2024 15:36:44 +0530 Subject: [PATCH 4/4] chore: use asynGen UX for SignSharedChain --- examples/buddybook/src/components/Chain/SignSharedChain.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/buddybook/src/components/Chain/SignSharedChain.tsx b/examples/buddybook/src/components/Chain/SignSharedChain.tsx index 459de77..b3eceb9 100644 --- a/examples/buddybook/src/components/Chain/SignSharedChain.tsx +++ b/examples/buddybook/src/components/Chain/SignSharedChain.tsx @@ -24,11 +24,12 @@ const SignSharedChain: React.FC = ({ chainsData, onChainUp } }, [chainsData, chainUUID, blockUUID]); - if (isLoading) { + if (isLoading && !block) { return ( - + +

      Looking for chain...

      );