Commit Graph

45 Commits

Author SHA1 Message Date
Gigi
c28052720e fix: save articles to localStorage cache after loading from relays
We were loading articles from relays but never saving them to cache,
which meant every refresh would query relays again. Now we:
1. Save to cache immediately after successfully loading from relays
2. Export saveToCache function for reuse
3. Add debug logs to track cache saves

This ensures articles are cached after first load, enabling instant
loading on subsequent visits/refreshes.
2025-10-31 00:41:08 +01:00
Gigi
d0f942c495 debug: add comprehensive logging to article loader
Add detailed debug logs prefixed with [article-loader] and [article-cache]
to track:
- Cache checks (hit/miss/expired)
- EventStore checks
- Relay queries and event streaming
- UI state updates
- Request lifecycle and abort conditions

This will help debug why articles are still loading from relays on refresh.
2025-10-31 00:39:29 +01:00
Gigi
907ef82efb fix: check cache synchronously before setting loading state
Move localStorage cache check outside async function to execute
immediately before any loading state is set. This prevents loading
skeletons from appearing when cached content is available.

Previously, cache was checked inside async function, allowing a render
cycle where loading=true was shown before cache could load content.
2025-10-31 00:38:13 +01:00
Gigi
415ff04345 fix: check localStorage cache before querying relays for articles
Previously, articles always loaded from relays on browser refresh because:
- EventStore is in-memory only and doesn't persist
- localStorage cache was only checked as last resort after relay queries failed

Now we check the localStorage cache immediately after EventStore,
before querying relays. This allows instant article loading from cache
on refresh without unnecessary relay queries.
2025-10-31 00:34:42 +01:00
Gigi
d6da27c634 fix: resolve all linting errors and type issues
- Remove unused setShowOfflineIndicator calls
- Remove unused areAllRelaysLocal import
- Fix duplicate key 'failedRelays' in console.log
- Replace 'any' types with proper HighlightEvent interface
- Add eslint-disable comments for intentionally excluded useEffect dependencies
- All linting errors resolved, type checks pass
2025-10-31 00:04:24 +01:00
Gigi
2083c2b8c6 fix: remove eventStore and setter functions from useEffect dependencies
- Remove eventStore from useArticleLoader and useExternalUrlLoader dependencies
- Remove setter functions from dependencies as they shouldn't change
- Only keep naddr/url and previewData/cachedUrlHighlights as dependencies
- This prevents content loaders from re-running when going offline
- Fixes the core issue where loading skeleton appears immediately on offline detection
2025-10-30 20:23:23 +01:00
Gigi
35a8411d9b fix: check EventStore before setting loading state
- Move EventStore check before setReaderLoading(true) call
- Only show loading skeleton if content not found in store and no preview data
- This prevents loading skeleton from appearing when cached content is available
- Fixes the core issue where offline mode shows loading skeleton with cached content
2025-10-30 20:21:59 +01:00
Gigi
15b3b5b990 fix: remove relayPool dependency from content loaders
- Remove relayPool from useEffect dependencies in useArticleLoader and useExternalUrlLoader
- This prevents content reloading when relay status changes (going offline/online)
- Content loaders now only re-run when the actual content identifier changes
- Fixes issue where loading skeleton appears when going offline with cached content
2025-10-30 20:20:07 +01:00
Gigi
ad56acb712 fix: prevent unnecessary relay queries when article content is cached
- Return early from useArticleLoader when content is found in EventStore
- This prevents loading skeleton from showing when going offline with cached content
- Improves offline experience by using locally cached article content
2025-10-30 20:18:06 +01:00
Gigi
92145af2bb feat: implement dynamic browser title based on content
- Add useDocumentTitle hook to manage document title dynamically
- Update useArticleLoader to set title when articles load
- Update useExternalUrlLoader to set title for external URLs/videos
- Update useEventLoader to set title for events
- Reset title to default when navigating away from content
- Browser title now shows article/video title instead of always 'Boris'
2025-10-25 01:07:55 +02:00
Gigi
1d989eae76 fix: improve article loading performance and error handling 2025-10-25 01:02:42 +02:00
Gigi
33d6e5882d refactor: simplify highlight loading code
- Remove redundant fallback mechanisms and backup effects
- Remove unnecessary parameters from useArticleLoader interface
- Keep only essential highlight loading logic
- Maintain DRY principle by eliminating duplicate code
- Simplify the codebase while preserving functionality
2025-10-25 01:00:36 +02:00
Gigi
0a62924b78 feat: implement robust highlight loading with fallback mechanisms
- Add detailed logging to track highlight loading process
- Implement fallback timeout mechanism to retry highlight loading after 2 seconds
- Add backup effect that triggers when article coordinate changes
- Ensure highlights are loaded reliably after article content is fully loaded
- Add console logging to help debug highlight loading issues
2025-10-25 00:59:26 +02:00
Gigi
a8ad346c5d feat: implement smart highlight clearing for articles
- Preserve highlights that belong to the current article when switching articles
- Only clear highlights that don't match the current article coordinate or event ID
- Improve user experience by maintaining relevant highlights during navigation
2025-10-25 00:54:02 +02:00
Gigi
465c24ed3a fix: resolve highlight loading issues for articles
- Add missing eventStore parameter to fetchHighlightsForArticle call
- Clear highlights immediately when starting to load new article
- Fix infinite loading spinners when articles have zero highlights
- Ensure highlights are properly stored and persisted
2025-10-25 00:52:49 +02:00
Gigi
ba263acdff fix: stop highlights loading spinner when article has no highlights 2025-10-22 15:40:18 +02:00
Gigi
3ff57c4b67 fix(lint): add previewData to useArticleLoader effect dependencies 2025-10-22 15:36:03 +02:00
Gigi
51c364ea53 feat(article): instant preview from blog cards - show title, image, summary, date immediately via navigation state while content loads 2025-10-22 15:33:37 +02:00
Gigi
48b5aa3a30 feat(article): instant load from eventStore when clicking bookmark cards - check store by coordinate before relay query 2025-10-22 15:29:08 +02:00
Gigi
d4483a2f91 fix(lint): resolve eslint warnings in useArticleLoader - add comment for empty catch, use settingsRef consistently 2025-10-22 15:26:16 +02:00
Gigi
3f7d726ae6 feat(article): local-first streaming loader using eventStore + queryEvents in useArticleLoader; emit immediately on first store/relay hit; finalize on EOSE 2025-10-22 15:22:39 +02:00
Gigi
6f1c31058f fix(reader): guard against stale article fetches overwriting current content/highlights via requestId in useArticleLoader 2025-10-22 13:41:46 +02:00
Gigi
7551a05aee fix(article): prevent re-fetch on settings change by memoizing via ref in useArticleLoader 2025-10-22 13:38:24 +02:00
Gigi
29918f78f9 refactor: remove eslint-disable comments by typing publish, fixing unused-vars, and updating effect deps 2025-10-21 07:21:01 +02:00
Gigi
dbed4ad253 fix: revert to inline mount tracking with useRef
- Replace useMountedState custom hook with inline useRef approach
- Set mountedRef.current = true at start of each effect run
- Ensures proper reset when navigating between articles
- Simpler and more reliable than custom hook approach
2025-10-20 18:05:02 +02:00
Gigi
b117b1e6cf fix: remove isMounted from useEffect dependencies
- isMounted is a stable function from useMountedState and shouldn't be in deps
- Including it was preventing effects from running correctly
- Fixes issue where articles wouldn't load (stuck on spinner)
2025-10-20 17:46:41 +02:00
Gigi
811d96dee0 refactor: extract common isMounted pattern into reusable useMountedState hook
- Create useMountedState hook to track component mount status
- Refactor useArticleLoader to use shared hook
- Refactor useExternalUrlLoader to use shared hook
- Remove duplicated isMounted pattern across both loaders
- Cleaner, more DRY code with same functionality
2025-10-20 16:33:05 +02:00
Gigi
21335d56dc fix: prevent infinite loading spinner by fixing race conditions in article/URL loaders
- Add isMounted flag to track component lifecycle in useArticleLoader
- Add isMounted flag to track component lifecycle in useExternalUrlLoader
- Remove setter functions from useEffect dependencies to prevent re-triggers
- Add cleanup functions to cancel pending state updates on unmount
- Check isMounted before all state updates in async operations
- Fixes issue where spinner would spin forever when loading articles
2025-10-20 15:00:39 +02:00
Gigi
e50af42c96 fix: import React types correctly in useArticleLoader
- Import Dispatch and SetStateAction directly from 'react'
- Fixes linting errors about React not being defined
- Resolves eslint no-undef errors
2025-10-20 13:34:48 +02:00
Gigi
31e203825d fix(types): correct setHighlights type to accept setState updater functions 2025-10-20 13:19:39 +02:00
Gigi
d2181ad772 fix(highlights): preserve immediate UI highlight after creation by merging streaming results instead of overwriting in article and external URL loaders 2025-10-20 09:07:42 +02:00
Gigi
4202807777 refactor: remove all console.log debug output 2025-10-19 22:35:45 +02:00
Gigi
b055294afc feat: add relay rebroadcast settings for caching and propagation
- Add two new settings:
  - Use local relay(s) as cache (default: enabled)
  - Rebroadcast events to all relays (default: disabled)
- Create rebroadcastService to handle rebroadcasting events
- Hook into article, bookmark, and highlight fetching services
- Automatically rebroadcast fetched events based on settings:
  - Articles when opened
  - Bookmarks when fetched
  - Highlights when fetched
- Add RelayRebroadcastSettings component with plane/globe icons
- Benefits:
  - Local caching for offline access
  - Content propagation across nostr network
  - User control over bandwidth usage
2025-10-09 13:01:38 +01:00
Gigi
48a9919db8 feat(reader): display article publication date
- Add published field to ReadableContent interface
- Pass published date from article loader through component chain
- Display formatted publication date in ReaderHeader with calendar icon
- Format date as 'MMMM d, yyyy' using date-fns
2025-10-09 12:15:28 +01:00
Gigi
22a02d228d fix: deduplicate highlights in streaming callbacks
- Replace array accumulation with Map keyed by highlight ID
- Prevents duplicate highlights when same event arrives from multiple relays
- Fix applied in useArticleLoader and useBookmarksData hooks
- Only updates UI when new unique highlight arrives
- Resolves issue where highlights appeared twice in sidebar
2025-10-08 12:55:27 +01:00
Gigi
d642c87527 fix: pass article summary through to ReadableContent
- Add summary field when converting ArticleContent to ReadableContent
- Fix contentLoader.ts to include article.summary
- Fix useArticleLoader.ts to include article.summary
- Article summaries now properly display in reader header
- Resolves missing summary display for kind:30023 articles
2025-10-08 12:41:03 +01:00
Gigi
a9847a8848 fix: add missing useEffect dependencies for article loading
- Fix useBookmarksData hook to include all callback dependencies
- Fix useArticleLoader hook to include all setter function dependencies
- Fix useExternalUrlLoader hook to include all setter function dependencies
- Ensures articles load properly when navigating
2025-10-07 22:04:12 +01:00
Gigi
a6ea97b731 fix: replace any types with proper NostrEvent types
- Replace any type with NostrEvent | undefined in Bookmarks component
- Replace any type with NostrEvent in useArticleLoader hook
- Remove incorrect bookmark-to-article assignment
- All linter warnings resolved
- Type checks passing
2025-10-05 23:16:05 +01:00
Gigi
290d9303b5 feat: add simple highlight creation feature
- Create HighlightButton component that appears on text selection
- Add highlightCreationService using EventFactory and HighlightBlueprint
- Integrate highlight button into ContentPanel with text selection detection
- Update Bookmarks to pass required props and refresh highlights after creation
- Publish highlights to NIP-84 relays automatically
- Only show button when user is logged in
2025-10-05 23:03:23 +01:00
Gigi
c07797ff7c fix: resolve all linting and type errors 2025-10-05 22:45:57 +01:00
Gigi
41fb51c357 feat: stream highlights progressively as they arrive from relays 2025-10-05 22:42:39 +01:00
Gigi
5e2abfa8c7 fix: display article immediately without waiting for highlights to load 2025-10-05 22:40:54 +01:00
Gigi
7cf2b7d35d fix: remove redundant setReaderLoading call in error handler 2025-10-05 22:39:51 +01:00
Gigi
fa52d61c20 fix(highlights): prevent highlights panel from auto-opening on article load 2025-10-05 22:28:07 +01:00
Gigi
4d95657bca refactor: keep Bookmarks.tsx under 210 lines by extracting logic
Extracted large functions into separate modules to follow DRY principles
and keep files manageable:

- Created useArticleLoader.ts hook (92 lines)
  - Handles article loading from naddr
  - Fetches article content and highlights
  - Sets up article coordinate for refresh

- Created contentLoader.ts utility (44 lines)
  - Handles both Nostr articles and web URLs
  - Unified content loading logic
  - Reusable across components

Result: Bookmarks.tsx reduced from 282 to 208 lines 

All files now under 210 line limit while maintaining functionality.
2025-10-05 12:47:32 +01:00