mirror of
https://github.com/dergigi/boris.git
synced 2026-01-29 03:34:43 +01:00
feat: centralize bookmark loading with streaming and auto-decrypt
Implemented centralized bookmark loading system: - Bookmarks loaded in App.tsx with streaming + auto-decrypt pattern - Load triggers: login, app mount, manual refresh only - No redundant fetching on route changes Changes: 1. bookmarkService.ts: Refactored fetchBookmarks for streaming - Events stream with onEvent callback - Auto-decrypt encrypted content (NIP-04/NIP-44) as events arrive - Progressive UI updates during loading 2. App.tsx: Added centralized bookmark state - bookmarks and bookmarksLoading state in AppRoutes - loadBookmarks function with streaming support - Load on mount if account exists (app reopen) - Load when activeAccount changes (login) - handleRefreshBookmarks for manual refresh - Pass props to all Bookmarks components 3. Bookmarks.tsx: Accept bookmarks as props - Receive bookmarks, bookmarksLoading, onRefreshBookmarks - Pass onRefreshBookmarks to useBookmarksData 4. useBookmarksData.ts: Simplified to accept bookmarks as props - Removed bookmark fetching logic - Removed handleFetchBookmarks function - Accept onRefreshBookmarks callback - Use onRefreshBookmarks in handleRefreshAll 5. Me.tsx: Removed fallback bookmark loading - Removed fetchBookmarks import and calls - Use bookmarks directly from props (centralized source) Benefits: - Single source of truth for bookmarks - No duplicate fetching across components - Streaming + auto-decrypt for better UX - Simpler, more maintainable code - DRY principle: one place for bookmark loading
This commit is contained in:
@@ -13,6 +13,7 @@ import { useHighlightCreation } from '../hooks/useHighlightCreation'
|
||||
import { useBookmarksUI } from '../hooks/useBookmarksUI'
|
||||
import { useRelayStatus } from '../hooks/useRelayStatus'
|
||||
import { useOfflineSync } from '../hooks/useOfflineSync'
|
||||
import { Bookmark } from '../types/bookmarks'
|
||||
import ThreePaneLayout from './ThreePaneLayout'
|
||||
import Explore from './Explore'
|
||||
import Me from './Me'
|
||||
@@ -24,9 +25,18 @@ export type ViewMode = 'compact' | 'cards' | 'large'
|
||||
interface BookmarksProps {
|
||||
relayPool: RelayPool | null
|
||||
onLogout: () => void
|
||||
bookmarks: Bookmark[]
|
||||
bookmarksLoading: boolean
|
||||
onRefreshBookmarks: () => Promise<void>
|
||||
}
|
||||
|
||||
const Bookmarks: React.FC<BookmarksProps> = ({ relayPool, onLogout }) => {
|
||||
const Bookmarks: React.FC<BookmarksProps> = ({
|
||||
relayPool,
|
||||
onLogout,
|
||||
bookmarks,
|
||||
bookmarksLoading,
|
||||
onRefreshBookmarks
|
||||
}) => {
|
||||
const { naddr, npub } = useParams<{ naddr?: string; npub?: string }>()
|
||||
const location = useLocation()
|
||||
const navigate = useNavigate()
|
||||
@@ -152,8 +162,6 @@ const Bookmarks: React.FC<BookmarksProps> = ({ relayPool, onLogout }) => {
|
||||
}, [navigationState, setIsHighlightsCollapsed, setSelectedHighlightId, navigate, location.pathname])
|
||||
|
||||
const {
|
||||
bookmarks,
|
||||
bookmarksLoading,
|
||||
highlights,
|
||||
setHighlights,
|
||||
highlightsLoading,
|
||||
@@ -166,12 +174,12 @@ const Bookmarks: React.FC<BookmarksProps> = ({ relayPool, onLogout }) => {
|
||||
} = useBookmarksData({
|
||||
relayPool,
|
||||
activeAccount,
|
||||
accountManager,
|
||||
naddr,
|
||||
externalUrl,
|
||||
currentArticleCoordinate,
|
||||
currentArticleEventId,
|
||||
settings
|
||||
settings,
|
||||
onRefreshBookmarks
|
||||
})
|
||||
|
||||
const {
|
||||
|
||||
@@ -9,7 +9,6 @@ import { useNavigate, useParams } from 'react-router-dom'
|
||||
import { Highlight } from '../types/highlights'
|
||||
import { HighlightItem } from './HighlightItem'
|
||||
import { fetchHighlights } from '../services/highlightService'
|
||||
import { fetchBookmarks } from '../services/bookmarkService'
|
||||
import { fetchAllReads, ReadItem } from '../services/readsService'
|
||||
import { fetchLinks } from '../services/linksService'
|
||||
import { BlogPostPreview, fetchBlogPostsFromAuthors } from '../services/exploreService'
|
||||
@@ -142,14 +141,7 @@ const Me: React.FC<MeProps> = ({ relayPool, activeTab: propActiveTab, pubkey: pr
|
||||
|
||||
try {
|
||||
if (!hasBeenLoaded) setLoading(true)
|
||||
try {
|
||||
await fetchBookmarks(relayPool, activeAccount, (newBookmarks) => {
|
||||
setBookmarks(newBookmarks)
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('Failed to load bookmarks:', err)
|
||||
setBookmarks([])
|
||||
}
|
||||
// Bookmarks come from centralized loading in App.tsx
|
||||
setLoadedTabs(prev => new Set(prev).add('reading-list'))
|
||||
} catch (err) {
|
||||
console.error('Failed to load reading list:', err)
|
||||
@@ -166,22 +158,8 @@ const Me: React.FC<MeProps> = ({ relayPool, activeTab: propActiveTab, pubkey: pr
|
||||
try {
|
||||
if (!hasBeenLoaded) setLoading(true)
|
||||
|
||||
// Ensure bookmarks are loaded
|
||||
let fetchedBookmarks: Bookmark[] = bookmarks
|
||||
if (bookmarks.length === 0) {
|
||||
try {
|
||||
await fetchBookmarks(relayPool, activeAccount, (newBookmarks) => {
|
||||
fetchedBookmarks = newBookmarks
|
||||
setBookmarks(newBookmarks)
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('Failed to load bookmarks:', err)
|
||||
fetchedBookmarks = []
|
||||
}
|
||||
}
|
||||
|
||||
// Derive reads from bookmarks immediately
|
||||
const initialReads = deriveReadsFromBookmarks(fetchedBookmarks)
|
||||
// Derive reads from bookmarks immediately (bookmarks come from centralized loading in App.tsx)
|
||||
const initialReads = deriveReadsFromBookmarks(bookmarks)
|
||||
const initialMap = new Map(initialReads.map(item => [item.id, item]))
|
||||
setReadsMap(initialMap)
|
||||
setReads(initialReads)
|
||||
@@ -190,7 +168,7 @@ const Me: React.FC<MeProps> = ({ relayPool, activeTab: propActiveTab, pubkey: pr
|
||||
|
||||
// Background enrichment: merge reading progress and mark-as-read
|
||||
// Only update items that are already in our map
|
||||
fetchAllReads(relayPool, viewingPubkey, fetchedBookmarks, (item) => {
|
||||
fetchAllReads(relayPool, viewingPubkey, bookmarks, (item) => {
|
||||
console.log('📈 [Reads] Enrichment item received:', {
|
||||
id: item.id.slice(0, 20) + '...',
|
||||
progress: item.readingProgress,
|
||||
@@ -230,22 +208,8 @@ const Me: React.FC<MeProps> = ({ relayPool, activeTab: propActiveTab, pubkey: pr
|
||||
try {
|
||||
if (!hasBeenLoaded) setLoading(true)
|
||||
|
||||
// Ensure bookmarks are loaded
|
||||
let fetchedBookmarks: Bookmark[] = bookmarks
|
||||
if (bookmarks.length === 0) {
|
||||
try {
|
||||
await fetchBookmarks(relayPool, activeAccount, (newBookmarks) => {
|
||||
fetchedBookmarks = newBookmarks
|
||||
setBookmarks(newBookmarks)
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('Failed to load bookmarks:', err)
|
||||
fetchedBookmarks = []
|
||||
}
|
||||
}
|
||||
|
||||
// Derive links from bookmarks immediately
|
||||
const initialLinks = deriveLinksFromBookmarks(fetchedBookmarks)
|
||||
// Derive links from bookmarks immediately (bookmarks come from centralized loading in App.tsx)
|
||||
const initialLinks = deriveLinksFromBookmarks(bookmarks)
|
||||
const initialMap = new Map(initialLinks.map(item => [item.id, item]))
|
||||
setLinksMap(initialMap)
|
||||
setLinks(initialLinks)
|
||||
|
||||
Reference in New Issue
Block a user