From e09be543bcb89001a8059f0fbd6c4c1fb7f99bab Mon Sep 17 00:00:00 2001 From: Gigi Date: Mon, 13 Oct 2025 16:50:43 +0200 Subject: [PATCH] feat: add caching to /me page for faster loading - Create meCache service to store highlights, bookmarks, and read articles - Seed Me component from cache on load to avoid empty flash - Show small spinner while refreshing if cached data is displayed - Update cache when highlights are deleted - Only show full loading screen if no cached data is available - Improves perceived performance similar to /explore page --- src/components/Me.tsx | 38 ++++++++++++++++++++++++++--- src/services/meCache.ts | 54 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 src/services/meCache.ts diff --git a/src/components/Me.tsx b/src/components/Me.tsx index 05f6f081..1486cb3f 100644 --- a/src/components/Me.tsx +++ b/src/components/Me.tsx @@ -17,6 +17,7 @@ import { BookmarkItem } from './BookmarkItem' import IconButton from './IconButton' import { ViewMode } from './Bookmarks' import { extractUrlsFromContent } from '../services/bookmarkHelpers' +import { getCachedMeData, setCachedMeData, updateCachedHighlights } from '../services/meCache' import { faBooks } from '../icons/customIcons' interface MeProps { @@ -47,6 +48,14 @@ const Me: React.FC = ({ relayPool }) => { setLoading(true) setError(null) + // Seed from cache if available to avoid empty flash + const cached = getCachedMeData(activeAccount.pubkey) + if (cached) { + setHighlights(cached.highlights) + setBookmarks(cached.bookmarks) + setReadArticles(cached.readArticles) + } + // Fetch highlights and read articles const [userHighlights, userReadArticles] = await Promise.all([ fetchHighlights(relayPool, activeAccount.pubkey), @@ -57,12 +66,19 @@ const Me: React.FC = ({ relayPool }) => { setReadArticles(userReadArticles) // Fetch bookmarks using callback pattern + let fetchedBookmarks: Bookmark[] = [] try { - await fetchBookmarks(relayPool, activeAccount, setBookmarks) + await fetchBookmarks(relayPool, activeAccount, (newBookmarks) => { + fetchedBookmarks = newBookmarks + setBookmarks(newBookmarks) + }) } catch (err) { console.warn('Failed to load bookmarks:', err) setBookmarks([]) } + + // Update cache with all fetched data + setCachedMeData(activeAccount.pubkey, userHighlights, fetchedBookmarks, userReadArticles) } catch (err) { console.error('Failed to load data:', err) setError('Failed to load data. Please try again.') @@ -75,7 +91,14 @@ const Me: React.FC = ({ relayPool }) => { }, [relayPool, activeAccount]) const handleHighlightDelete = (highlightId: string) => { - setHighlights(prev => prev.filter(h => h.id !== highlightId)) + setHighlights(prev => { + const updated = prev.filter(h => h.id !== highlightId) + // Update cache when highlight is deleted + if (activeAccount) { + updateCachedHighlights(activeAccount.pubkey, updated) + } + return updated + }) } const getPostUrl = (post: BlogPostPreview) => { @@ -110,7 +133,10 @@ const Me: React.FC = ({ relayPool }) => { .filter(hasContentOrUrl) .sort((a, b) => ((b.added_at || 0) - (a.added_at || 0)) || ((b.created_at || 0) - (a.created_at || 0))) - if (loading) { + // Only show full loading screen if we don't have any data yet + const hasData = highlights.length > 0 || bookmarks.length > 0 || readArticles.length > 0 + + if (loading && !hasData) { return (
@@ -228,6 +254,12 @@ const Me: React.FC = ({ relayPool }) => {
{activeAccount && } + {loading && hasData && ( +
+ +
+ )} +