- Show all map keys when looking up reading progress
- Show d-tag generation from naddr in save flow
- This will help identify if naddr encoding/decoding is causing mismatch
- Add logs in readingProgressController: processing events, emitting to listeners
- Add logs in Explore component: receiving updates, looking up progress
- Add logs in BlogPostCard: rendering with progress
- Add detailed logs in processReadingProgress: event parsing, naddr conversion
- All logs prefixed with [progress] for easy filtering
- Add readingProgressController following the same pattern as highlightsController and writingsController
- Controller manages reading progress (kind:39802) centrally with subscriptions
- Remove duplicated reading progress loading logic from Explore, Profile, and Me components
- Components now subscribe to controller updates instead of loading data individually
- Supports incremental sync and force reload
- Improves efficiency and maintainability
- Add reading progress loading and display in Explore component
- Add reading progress loading and display in Profile component
- Add reading progress loading and display in Me writings tab
- Reading progress now shows as colored progress bar in all blog post cards
- Progress colors: gray (started 0-10%), blue (reading 10-95%), green (completed 95%+)
- Remove cachedHighlights, cachedWritings, myHighlights from useEffect deps
- These are derived from eventStore and caused infinite refetch loop
- Content is still seeded from cache but doesn't trigger re-fetches
- Allow exploring nostrverse writings and highlights without account
- Default to nostrverse visibility when logged out
- Update visibility settings when login state changes
- Add useStoreTimeline hook for reactive EventStore queries
- Add dedupe helpers for highlights and writings
- Explore: seed highlights and writings from store instantly
- Article sidebar: seed article-specific highlights from store
- External URLs: seed URL-specific highlights from store
- Profile pages: seed other-profile highlights and writings from store
- Remove debug logging
- All data loads from cache first, then updates with fresh data
- Follows DRY principles with single reusable hook
- Use eventStore.timeline() to query cached highlights
- Seed Explore page with cached highlights immediately
- Provides instant display of nostrverse highlights from store
- Fresh data still fetched in background and merged
- Follows applesauce pattern with useObservableMemo
- Add key prop based on activeTab to wrapper div
- Forces complete unmount/remount of content when switching tabs
- Prevents DOM element reuse that was causing blog posts to bleed into highlights tab
- Use consistent deduplication key (author:d-tag) for replaceable events
- Prevents duplicate blog posts when same article has multiple event IDs
- Streaming updates now properly replace older versions with newer ones
- Fixes issue where same blog post card appeared multiple times
- Add eventStore parameter to fetchNostrverseBlogPosts
- Add eventStore parameter to fetchNostrverseHighlights
- Pass eventStore from Explore component to nostrverse fetchers
- Store all nostrverse blog posts and highlights in event store
- Enables offline access to nostrverse content
Add user setting to control default visibility scope in /explore page.
Changes:
- Add defaultExploreScopeNostrverse/Friends/Mine to UserSettings type
- Add "Default Explore Scope" setting in ReadingDisplaySettings UI
- Update Explore component to use defaultExploreScope settings
- Set default to friends-only (nostrverse: false, friends: true, mine: false)
Users can now configure which content types (nostrverse/friends/mine)
are visible by default when visiting the explore page, separate from
the highlight visibility settings.
Remove unnecessary prop drilling of myHighlights/myHighlightsLoading.
Components now subscribe directly to highlightsController (DRY principle).
Changes:
- Explore: Subscribe to controller directly, no props needed
- Me: Subscribe to controller directly, no props needed
- Bookmarks: Remove myHighlights props (no longer passes through)
- App: Remove highlights state, controller manages it internally
Benefits:
- ✅ Simpler code (no prop drilling through 3 layers)
- ✅ More DRY (single source of truth in controller)
- ✅ Consistent with applesauce patterns (like useActiveAccount)
- ✅ Less boilerplate (removed ~30 lines of prop passing)
- ✅ Controller encapsulates all state management
Pattern: Components import and subscribe to controller directly,
just like they use Hooks.useActiveAccount() or other applesauce hooks.
- Pass myHighlightsLoading state from controller through App → Bookmarks → Explore/Me
- Update Explore showSkeletons logic to include myHighlightsLoading
- Update Me showSkeletons logic to include myHighlightsLoading for own profile
- Sync myHighlights to Me component via useEffect for real-time updates
- Remove highlightsController import from Me (now uses props)
Benefits:
- Better UX with skeleton placeholders instead of empty/spinner states
- Consistent loading experience across Explore and Me pages
- Clear visual feedback when highlights are loading from controller
- Smooth transition from skeleton to actual content
- Pass myHighlights from controller through App.tsx → Bookmarks → Explore
- Merge controller highlights with friends/nostrverse highlights
- Seed Explore with myHighlights immediately (no re-fetch needed)
- Eliminate redundant fetching of user's own highlights
- Improve performance and consistency across the app
Benefits:
- User's highlights appear instantly in /explore (already loaded)
- No duplicate fetching of same data
- DRY principle - single source of truth for user highlights
- Better offline support (highlights from controller are in event store)
- Match marked-as-read event IDs to bookmark coordinate IDs
- Use eventStore to lookup events and build coordinates from them
- Add both event ID and coordinate format to markedAsReadIds set
- This fixes filtering of bookmarked articles by reading progress
- Apply same fix to both Bookmarks and Explore components
- Fetch marked-as-read articles in useBookmarksData and Explore
- Pass markedAsReadIds through component chain (Bookmarks -> ThreePaneLayout -> BookmarkList)
- Display 100% progress for marked articles in all views (Archive, Bookmarks, Explore)
- Update filter logic to treat marked articles as completed
- Marked articles show green 100% progress bar
- Marked articles only appear in 'completed' or 'all' filters
- Remove reading position tracking from Me.tsx (not needed when all are marked)
- Clean up unused imports and variables
- Add reading position loading to Explore component
- Add reading position loading to useBookmarksData hook
- Display progress bars in Explore tab blog posts
- Display progress bars in Bookmarks large preview view
- Progress shown as colored bar (green for completed, orange for in-progress)
- Only shown for kind:30023 articles with saved reading positions
- Requires syncReadingPosition setting to be enabled
- HighlightItem now handles navigation internally
- Remove duplicate navigation logic from Explore component
- Simplifies code and ensures consistent behavior across all highlight displays
Replaced 'No X yet. Pull to refresh!' messages with spinning loaders for:
- No highlights yet (Me & Explore)
- No bookmarks yet (Me)
- No read articles yet (Me)
- No articles written yet (Me)
- No blog posts yet (Explore)
This provides better UX by showing an active loading state instead of
static empty state messages.
- Add level-based colored borders to blog post cards (mine/friends/nostrverse)
- Updated BlogPostCard to accept and apply level prop
- Modified Explore.tsx to classify blog posts by relationship level
- Added CSS styling using settings colors for visual distinction
- Highlights already had this feature, now writings have it too