From 0ea489a37b1ea64d90fbf9b0b01020a3f05c7235 Mon Sep 17 00:00:00 2001 From: Danish Arora Date: Thu, 23 Oct 2025 18:20:16 +0530 Subject: [PATCH] chore: upgrade to latest waku, hydration improvevments --- app/src/components/ActivityFeed.tsx | 5 +- app/src/components/CellList.tsx | 6 +- app/src/components/Header.tsx | 2 +- app/src/pages/FeedPage.tsx | 6 +- package-lock.json | 98 +++++++++---------- packages/core/package.json | 2 +- packages/react/README.md | 2 +- packages/react/src/v1/hooks/useNetwork.ts | 1 + .../react/src/v1/provider/StoreWiring.tsx | 10 ++ packages/react/src/v1/store/opchanStore.ts | 2 + 10 files changed, 76 insertions(+), 58 deletions(-) diff --git a/app/src/components/ActivityFeed.tsx b/app/src/components/ActivityFeed.tsx index 0074600..e65052d 100644 --- a/app/src/components/ActivityFeed.tsx +++ b/app/src/components/ActivityFeed.tsx @@ -38,7 +38,7 @@ const ActivityFeed: React.FC = () => { const { content, network } = useForum(); const { posts, comments, cells, commentsByPost } = content; - const { isConnected } = network; + const { isHydrated } = network; const combinedFeed: FeedItem[] = useMemo(() => { @@ -144,7 +144,8 @@ const ActivityFeed: React.FC = () => { ); }; - if (!isConnected) { + // Show loading skeleton only while store is hydrating + if (!isHydrated) { return (
{[...Array(5)].map((_, i) => ( diff --git a/app/src/components/CellList.tsx b/app/src/components/CellList.tsx index 702d475..58942be 100644 --- a/app/src/components/CellList.tsx +++ b/app/src/components/CellList.tsx @@ -1,6 +1,6 @@ import { useState, useMemo } from 'react'; import { Link } from 'react-router-dom'; -import { useContent, usePermissions } from '@/hooks'; +import { useContent, usePermissions, useNetwork } from '@/hooks'; import { Layout, MessageSquare, @@ -143,6 +143,7 @@ const CellList = () => { const { cellsWithStats } = useContent(); const content = useContent(); const { canCreateCell } = usePermissions(); + const { isHydrated } = useNetwork(); const [sortOption, setSortOption] = useState('relevance'); // Apply sorting to cells @@ -150,7 +151,8 @@ const CellList = () => { return sortCells(cellsWithStats, sortOption); }, [cellsWithStats, sortOption]); - if (!cellsWithStats.length) { + // Only show loading if store is not yet hydrated + if (!isHydrated && !cellsWithStats.length) { return (
diff --git a/app/src/components/Header.tsx b/app/src/components/Header.tsx index cd292d8..4f44010 100644 --- a/app/src/components/Header.tsx +++ b/app/src/components/Header.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { Link, useLocation } from 'react-router-dom'; import { useAuth, useForum, useNetwork, useUIState } from '@/hooks'; import { EVerificationStatus } from '@opchan/core'; diff --git a/app/src/pages/FeedPage.tsx b/app/src/pages/FeedPage.tsx index c95f7ca..6a75121 100644 --- a/app/src/pages/FeedPage.tsx +++ b/app/src/pages/FeedPage.tsx @@ -12,12 +12,13 @@ import { import PostCard from '@/components/PostCard'; import FeedSidebar from '@/components/FeedSidebar'; import { ModerationToggle } from '@/components/ui/moderation-toggle'; -import { useAuth, useContent } from '@/hooks'; +import { useAuth, useContent, useNetwork } from '@/hooks'; import { EVerificationStatus } from '@opchan/core'; import { sortPosts, SortOption } from '@/utils/sorting'; const FeedPage: React.FC = () => { const content = useContent(); const { verificationStatus } = useAuth(); + const { isHydrated } = useNetwork(); const [sortOption, setSortOption] = useState('relevance'); const allPosts = useMemo( @@ -25,8 +26,9 @@ const FeedPage: React.FC = () => { [content.posts, sortOption] ); - // Loading skeleton + // Loading skeleton - only show if store is not yet hydrated if ( + !isHydrated && !content.posts.length && !content.comments.length && !content.cells.length diff --git a/package-lock.json b/package-lock.json index c40fc28..9d186a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5647,17 +5647,17 @@ } }, "node_modules/@waku/core": { - "version": "0.0.40-79dfb35.0", - "resolved": "https://registry.npmjs.org/@waku/core/-/core-0.0.40-79dfb35.0.tgz", - "integrity": "sha512-+94ez/4zZDQffAK/ERzXOkqCOlMh28/EEtTmqdaahSLrpc3EgqdIsDC8uUPddkOSDoaJ2Y657gm4WZ4PjyRmOQ==", + "version": "0.0.40-ff9c430.0", + "resolved": "https://registry.npmjs.org/@waku/core/-/core-0.0.40-ff9c430.0.tgz", + "integrity": "sha512-+ZY3OgAcIvazZrwX31lh3RDDtye/m4+WPyqNqrMEG+Ybd88ZJH8svdF9BxldPOltDBkM/5h2bsWoon6jLuGefw==", "license": "MIT OR Apache-2.0", "dependencies": { "@libp2p/ping": "2.0.35", "@noble/hashes": "^1.3.2", - "@waku/enr": "0.0.34-79dfb35.0", - "@waku/interfaces": "0.0.35-79dfb35.0", - "@waku/proto": "0.0.15-79dfb35.0", - "@waku/utils": "0.0.28-79dfb35.0", + "@waku/enr": "0.0.34-ff9c430.0", + "@waku/interfaces": "0.0.35-ff9c430.0", + "@waku/proto": "0.0.15-ff9c430.0", + "@waku/utils": "0.0.28-ff9c430.0", "debug": "^4.3.4", "it-all": "^3.0.4", "it-length-prefixed": "^9.0.4", @@ -5712,16 +5712,16 @@ } }, "node_modules/@waku/discovery": { - "version": "0.0.13-79dfb35.0", - "resolved": "https://registry.npmjs.org/@waku/discovery/-/discovery-0.0.13-79dfb35.0.tgz", - "integrity": "sha512-YNR7ThBjerUqqK0dOPAartpx5OeQN3r3xmuabUm8SCnKKXFLbB7WFBtSwu3X0O4GoalhtC9fAJhkia91A6CZEQ==", + "version": "0.0.13-ff9c430.0", + "resolved": "https://registry.npmjs.org/@waku/discovery/-/discovery-0.0.13-ff9c430.0.tgz", + "integrity": "sha512-FGmiaXawE9JxP2VTwVbFC8Qiafh8p1t4ahcDu6Rq0aWh5mNS0qVZj0vDCUMy3HjB9CtHO6+M6g/1u6FPYd9mXQ==", "license": "MIT OR Apache-2.0", "dependencies": { - "@waku/core": "0.0.40-79dfb35.0", - "@waku/enr": "0.0.34-79dfb35.0", - "@waku/interfaces": "0.0.35-79dfb35.0", - "@waku/proto": "0.0.15-79dfb35.0", - "@waku/utils": "0.0.28-79dfb35.0", + "@waku/core": "0.0.40-ff9c430.0", + "@waku/enr": "0.0.34-ff9c430.0", + "@waku/interfaces": "0.0.35-ff9c430.0", + "@waku/proto": "0.0.15-ff9c430.0", + "@waku/utils": "0.0.28-ff9c430.0", "debug": "^4.3.4", "dns-over-http-resolver": "^3.0.8", "hi-base32": "^0.5.1", @@ -5732,9 +5732,9 @@ } }, "node_modules/@waku/enr": { - "version": "0.0.34-79dfb35.0", - "resolved": "https://registry.npmjs.org/@waku/enr/-/enr-0.0.34-79dfb35.0.tgz", - "integrity": "sha512-suGFUu94gizghRQ+gNjTqR4zXMDK91FBlIn0EeALwVIboHX1MUExMjd58qgQ8biWdcJpnB/NiyiobK+5X46U7Q==", + "version": "0.0.34-ff9c430.0", + "resolved": "https://registry.npmjs.org/@waku/enr/-/enr-0.0.34-ff9c430.0.tgz", + "integrity": "sha512-bJc3IJ9b17B4nAa8S6n4a66fvx2eblyaS0MtzGqEcTTtEr+c//GScH8Xm/2oZ4bdyf/dm6iP1/ZeApvD9Wo+XQ==", "license": "MIT OR Apache-2.0", "dependencies": { "@ethersproject/rlp": "^5.7.0", @@ -5742,7 +5742,7 @@ "@libp2p/peer-id": "5.1.7", "@multiformats/multiaddr": "^12.0.0", "@noble/secp256k1": "^1.7.1", - "@waku/utils": "0.0.28-79dfb35.0", + "@waku/utils": "0.0.28-ff9c430.0", "debug": "^4.3.4", "js-sha3": "^0.9.2" }, @@ -5786,18 +5786,18 @@ } }, "node_modules/@waku/interfaces": { - "version": "0.0.35-79dfb35.0", - "resolved": "https://registry.npmjs.org/@waku/interfaces/-/interfaces-0.0.35-79dfb35.0.tgz", - "integrity": "sha512-3zBBpblsSrLHUAOjkQ+js0G5/TeNS4PERgR587caxn75xNn7Fd8WvgAM1xhMbtQU08twDZFGXKaJu3m9zCOOmA==", + "version": "0.0.35-ff9c430.0", + "resolved": "https://registry.npmjs.org/@waku/interfaces/-/interfaces-0.0.35-ff9c430.0.tgz", + "integrity": "sha512-m6az/AVkCF7nSlZsxKtRgPmyPVEjKg6LREnOWNIyAA2uCvesx00JxEN7DhkmgST+wNrH5+1LgoyE6mXTcSDqTw==", "license": "MIT OR Apache-2.0", "engines": { "node": ">=22" } }, "node_modules/@waku/proto": { - "version": "0.0.15-79dfb35.0", - "resolved": "https://registry.npmjs.org/@waku/proto/-/proto-0.0.15-79dfb35.0.tgz", - "integrity": "sha512-lH2a74lNzXKNpALDWIMLFfNMmfJtd+lAFgLhMEu3lHBVCgu1SVXy54fBk3X08A/cfOZSzuW0kStlND6GsYQOyA==", + "version": "0.0.15-ff9c430.0", + "resolved": "https://registry.npmjs.org/@waku/proto/-/proto-0.0.15-ff9c430.0.tgz", + "integrity": "sha512-JuPcioC2ry7do5Sa2TABjaJ4uQ4+jAbaZsjiir5OKmZI5krCv1BqKoZehY+BaX1lMerDfrGAXMpNQHjykfbthw==", "license": "MIT OR Apache-2.0", "dependencies": { "protons-runtime": "^5.4.0" @@ -5807,9 +5807,9 @@ } }, "node_modules/@waku/sdk": { - "version": "0.0.36-79dfb35.0", - "resolved": "https://registry.npmjs.org/@waku/sdk/-/sdk-0.0.36-79dfb35.0.tgz", - "integrity": "sha512-mbr8dzHLq5T4K4ShfJwOlPeAY2v9ABvZ5mUbViFsKgfwO14vQV4X80P/lgyiFYwQg8r6ZL7Mc9UkRz/FArgSDg==", + "version": "0.0.36-ff9c430.0", + "resolved": "https://registry.npmjs.org/@waku/sdk/-/sdk-0.0.36-ff9c430.0.tgz", + "integrity": "sha512-BO6svBNw1B+HeCioKDYeFsmsxhBHzbLkxPYqVMm8FDTngmZGj1dywli4YDMm8cgwWux+Kp9TcoDEkqvKgE0ctw==", "license": "MIT OR Apache-2.0", "dependencies": { "@chainsafe/libp2p-noise": "16.1.3", @@ -5820,12 +5820,12 @@ "@libp2p/websockets": "9.2.16", "@noble/hashes": "^1.3.3", "@types/lodash.debounce": "^4.0.9", - "@waku/core": "0.0.40-79dfb35.0", - "@waku/discovery": "0.0.13-79dfb35.0", - "@waku/interfaces": "0.0.35-79dfb35.0", - "@waku/proto": "0.0.15-79dfb35.0", - "@waku/sds": "0.0.8-79dfb35.0", - "@waku/utils": "0.0.28-79dfb35.0", + "@waku/core": "0.0.40-ff9c430.0", + "@waku/discovery": "0.0.13-ff9c430.0", + "@waku/interfaces": "0.0.35-ff9c430.0", + "@waku/proto": "0.0.15-ff9c430.0", + "@waku/sds": "0.0.8-ff9c430.0", + "@waku/utils": "0.0.28-ff9c430.0", "libp2p": "2.8.11", "lodash.debounce": "^4.0.8" }, @@ -5834,15 +5834,15 @@ } }, "node_modules/@waku/sds": { - "version": "0.0.8-79dfb35.0", - "resolved": "https://registry.npmjs.org/@waku/sds/-/sds-0.0.8-79dfb35.0.tgz", - "integrity": "sha512-hhzlLwgSsDYYmIBBZprJWkCUkI6oJfrgUgMAyrC04JIQbzvuOF0sRHHUY4C6VQKmxUJFU0Lj+RRPj1pR6ezk9w==", + "version": "0.0.8-ff9c430.0", + "resolved": "https://registry.npmjs.org/@waku/sds/-/sds-0.0.8-ff9c430.0.tgz", + "integrity": "sha512-st2/2QeId6kFyK53L3aV4cNTyYCfrM7As77k21nlgo0PEHKHyPPFuoIkZUwRIWO6qM9ohXgiIU3RVTioEtZuTA==", "license": "MIT OR Apache-2.0", "dependencies": { "@libp2p/interface": "2.10.4", "@noble/hashes": "^1.7.1", - "@waku/proto": "0.0.15-79dfb35.0", - "@waku/utils": "0.0.28-79dfb35.0", + "@waku/proto": "0.0.15-ff9c430.0", + "@waku/utils": "0.0.28-ff9c430.0", "chai": "^5.1.2", "lodash": "^4.17.21" }, @@ -5866,13 +5866,13 @@ } }, "node_modules/@waku/utils": { - "version": "0.0.28-79dfb35.0", - "resolved": "https://registry.npmjs.org/@waku/utils/-/utils-0.0.28-79dfb35.0.tgz", - "integrity": "sha512-wwNg+qGI5MmoT+DD+1+AUM6SMJvOgqcXawVVlXc83UMgWgU44YshBdfrhsxv/CPUfIN2l6i39uU6zhDN5INT4A==", + "version": "0.0.28-ff9c430.0", + "resolved": "https://registry.npmjs.org/@waku/utils/-/utils-0.0.28-ff9c430.0.tgz", + "integrity": "sha512-6tBSQ/X+vzoLV3R573c80XLESZq4qWWSlyXtG4se/+RanQU1om9cSkAzrAlm9ZhO6IcrpLlNgeOsv/dIUIz+Fw==", "license": "MIT OR Apache-2.0", "dependencies": { "@noble/hashes": "^1.3.2", - "@waku/interfaces": "0.0.35-79dfb35.0", + "@waku/interfaces": "0.0.35-ff9c430.0", "chai": "^4.3.10", "debug": "^4.3.4", "uint8arrays": "^5.0.1" @@ -14409,9 +14409,9 @@ "license": "MIT" }, "node_modules/quick-lru": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.2.0.tgz", - "integrity": "sha512-fG4L8TlD1CacJiGMGPxM1/K8l/GaKL2eFQZ6DWAjxZYxSf07DkumbC/Mhh+u/NHvxkfQVL25By0pxBS8QE9ZrQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-7.3.0.tgz", + "integrity": "sha512-k9lSsjl36EJdK7I06v7APZCbyGT2vMTsYSRX1Q2nbYmnkBqgUhRkAuzH08Ciotteu/PLJmIF2+tti7o3C/ts2g==", "license": "MIT", "engines": { "node": ">=18" @@ -17980,7 +17980,7 @@ "@reown/appkit-adapter-wagmi": "^1.7.17", "@reown/appkit-common": "^1.7.17", "@reown/appkit-controllers": "^1.7.17", - "@waku/sdk": "^0.0.36-79dfb35.0", + "@waku/sdk": "0.0.36-ff9c430.0", "clsx": "^2.1.1", "ordiscan": "^1.3.0", "tailwind-merge": "^2.5.2", @@ -18006,9 +18006,9 @@ }, "packages/react": { "name": "@opchan/react", - "version": "1.0.2", + "version": "1.1.0", "dependencies": { - "@opchan/core": "^1.0.0" + "@opchan/core": "file:../core" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/packages/core/package.json b/packages/core/package.json index b8c5d6a..8f7ad68 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -44,7 +44,7 @@ "@reown/appkit-adapter-wagmi": "^1.7.17", "@reown/appkit-common": "^1.7.17", "@reown/appkit-controllers": "^1.7.17", - "@waku/sdk": "^0.0.36-79dfb35.0", + "@waku/sdk": "0.0.36-ff9c430.0", "clsx": "^2.1.1", "ordiscan": "^1.3.0", "tailwind-merge": "^2.5.2", diff --git a/packages/react/README.md b/packages/react/README.md index f225b4f..71a600c 100644 --- a/packages/react/README.md +++ b/packages/react/README.md @@ -135,7 +135,7 @@ export function Connect() { - Functions: `canModerate(cellId)`, `check(action, cellId?) → { allowed, reason }`, `reasons`. - **`useNetwork()`** → connection state - - Data: `isConnected`, `statusMessage`, `issues`, `canRefresh`. + - Data: `isConnected`, `statusMessage`, `issues`, `isHydrated`, `canRefresh`. - Actions: `refresh()` — triggers a light data refresh via core. - **`useUIState(key, defaultValue, category?)`** → persisted UI state diff --git a/packages/react/src/v1/hooks/useNetwork.ts b/packages/react/src/v1/hooks/useNetwork.ts index 82ce639..ee5f352 100644 --- a/packages/react/src/v1/hooks/useNetwork.ts +++ b/packages/react/src/v1/hooks/useNetwork.ts @@ -19,6 +19,7 @@ export function useNetwork() { isConnected: network.isConnected, statusMessage: network.statusMessage, issues: network.issues, + isHydrated: network.isHydrated, canRefresh: true, refresh, } as const; diff --git a/packages/react/src/v1/provider/StoreWiring.tsx b/packages/react/src/v1/provider/StoreWiring.tsx index 20bb403..abd1ab6 100644 --- a/packages/react/src/v1/provider/StoreWiring.tsx +++ b/packages/react/src/v1/provider/StoreWiring.tsx @@ -78,6 +78,16 @@ export const StoreWiring: React.FC = () => { } } catch (e) { console.error('Initial hydrate failed', e); + } finally { + // Mark hydration as complete regardless of success or failure + // This allows forum actions even when no content is loaded + setOpchanState(prev => ({ + ...prev, + network: { + ...prev.network, + isHydrated: true, + }, + })); } }; diff --git a/packages/react/src/v1/store/opchanStore.ts b/packages/react/src/v1/store/opchanStore.ts index 5036734..ee69208 100644 --- a/packages/react/src/v1/store/opchanStore.ts +++ b/packages/react/src/v1/store/opchanStore.ts @@ -46,6 +46,7 @@ export interface NetworkSlice { isConnected: boolean; statusMessage: string; issues: string[]; + isHydrated: boolean; } export interface OpchanState { @@ -85,6 +86,7 @@ const defaultState: OpchanState = { isConnected: false, statusMessage: 'connecting…', issues: [], + isHydrated: false, }, };