Commit Graph

1753 Commits

Author SHA1 Message Date
Gigi
e17e1bc824 fix(lint): resolve unused var and empty catch issues 2025-10-20 00:47:11 +02:00
Gigi
948674ae8c feat(reading-progress): stream mark-as-read reactions non-blockingly and emit updates as they arrive 2025-10-20 00:45:35 +02:00
Gigi
431f14f56d feat(reads): move highlighted filter next to All for prominence 2025-10-20 00:44:03 +02:00
Gigi
4cc9d557a0 feat(reads): add emoji filter, refine completed to 95%+, and show checkmark only at >=95% progress 2025-10-20 00:43:31 +02:00
Gigi
cc60f9584a temp: disable mark-as-read reactions loading due to queryEvents hanging
Temporarily skip loading mark-as-read reactions to unblock the reads feature.
Focus on getting reading progress working first.

TODO: Debug why queryEvents hangs when querying kind:7 and kind:17 reactions.
The Promise never resolves even though we're not using timeouts.
2025-10-20 00:38:14 +02:00
Gigi
94f1f9035b debug: add logging before/after queryEvents calls for reactions 2025-10-20 00:35:51 +02:00
Gigi
e5b1594933 feat: add listener for markedAsReadChanged events
Implemented event listener pattern in readingProgressController:
- Added onMarkedAsReadChanged() method for subscribers
- Added emitMarkedAsReadChanged() to notify when marked IDs update
- Call emitMarkedAsReadChanged() after loading reactions

In Me.tsx:
- Subscribe to onMarkedAsReadChanged() in new useEffect
- When fired, rebuild reads list with new marked-as-read items
- Include marked-only items (no progress event)

Now when reactions finish loading in background, /me/reads/completed
will update automatically with newly marked articles.
2025-10-20 00:34:38 +02:00
Gigi
2bf9b9789b debug: add detailed logging to mark-as-read reactions loading
Added comprehensive logging to see:
- When reactions queries start and complete
- How many kind:17 and kind:7 events are returned
- What reactions have MARK_AS_READ_EMOJI content
- Event ID to naddr mapping progress
- Final count of markedAsReadIds

This will help identify why markedAsReadIds is empty.
2025-10-20 00:33:01 +02:00
Gigi
d3405a4029 refactor: use bookmarkController pattern in readingProgressController
Non-blocking, background loading pattern:
- Subscribe to eventStore timeline immediately (returns right away)
- Mark as loaded immediately
- Fire-and-forget background queries for reading progress from relays
- Fire-and-forget background queries for mark-as-read reactions
- All updates stream via eventStore subscription

No timeouts. No blocking awaits. Updates arrive progressively as relays
respond, UI shows data as soon as eventStore delivers it.
2025-10-20 00:29:39 +02:00
Gigi
763f7bef4d debug: add granular logging to identify where loading hangs
Added logs at each step:
- Setting up timeline subscription
- Timeline subscription ready
- Querying reading progress events
- Got reading progress events count
- Generation changed abort

This will show exactly which step is blocking.
2025-10-20 00:23:04 +02:00
Gigi
e8e629f4e1 fix: prevent concurrent start() calls in readingProgressController
Added isLoading flag to block multiple start() calls from running in parallel.
The repeated start() calls were all waiting on queryEvents() calls,
creating a thundering herd that prevented any from completing.

Now only one start() runs at a time, and concurrent calls are skipped
with a console log.
2025-10-20 00:18:23 +02:00
Gigi
a0829e834f feat: mirror debug behavior in Me tabs for MARK_AS_READ
- Reads (/me/reads/completed): fetch kind:7 📚 reactions and map #e -> 30023 naddr; include as completed reads
- Links (/me/links/completed): fetch kind:17 📚 reactions and use #r URL; include as completed links
- Keep progress-based items from readingProgressController, but explicitly add marked-only items per tab

This matches the debug page behavior and splits articles vs links cleanly.
2025-10-20 00:00:00 +02:00
Gigi
ff938aa384 feat(reads): include marked-as-read-only items in /me/reads
If an article or URL is marked as read (📚) but has no reading
progress event yet, include it in the reads list so the 'completed'
filter surfaces it.

Uses readingProgressController.getMarkedAsReadIds() to synthesize
ReadItems for marked-only entries.
2025-10-19 23:57:20 +02:00
Gigi
3991bfeeb2 fix: move lastLoadedPubkey assignment to end of start() method
The bug: start() was setting lastLoadedPubkey at the beginning, so if
start() got called twice (which it was), the second call would see
isLoadedFor(pubkey) return true and skip the entire loading process,
including fetching mark-as-read reactions.

Fix: Only set lastLoadedPubkey AFTER all fetching is complete. This
ensures that concurrent start() calls don't skip the loading.

This allows kind:7 and kind:17 mark-as-read reactions to be fetched
and tracked properly.
2025-10-19 23:54:44 +02:00
Gigi
e8c35c8914 debug: add module-level log to confirm module is loaded
If this log doesn't appear in console, the module isn't being imported at all.
2025-10-19 23:53:31 +02:00
Gigi
46345c154b debug: add log before fetching mark-as-read reactions
Shows we reached the point where we're about to fetch kind:7/kind:17 reactions.
2025-10-19 23:53:00 +02:00
Gigi
f43dae92aa debug: add start() method logs to confirm controller initialization
Added initial logs to show:
- When start() is called
- Whether already loaded (and skipped)

This helps confirm the controller is even being initialized.
2025-10-19 23:52:24 +02:00
Gigi
99c164a5e9 debug: add detailed logging to understand markedAsReadIds population
Added:
- getMarkedAsReadIds() method to expose markedAsReadIds for debugging
- Final state logging showing all progressMap keys and markedAsReadIds
- Comprehensive logging throughout kind:7/kind:17 processing

This will help identify why markedAsRead articles aren't showing in /me/reads/completed.
Check console logs to see:
1. All progressMap entries (nadrs)
2. All markedAsReadIds entries
3. Step-by-step kind:7 and kind:17 processing
2025-10-19 23:51:05 +02:00
Gigi
569b4357f2 fix: skip title fetching for raw event IDs in HighlightCitation
The eventReference can be either:
1. Raw event ID (hex string) - from event pointers
2. Coordinate string (kind:pubkey:identifier) - from address pointers
3. Already-encoded naddr - from some sources

Raw event IDs cannot be converted to nadrs without additional context
(we don't have the kind, pubkey, or identifier), so skip title fetching
for them to avoid bech32 decoding errors.

Fixes console errors:
- 'Invalid checksum in <hex>'
- 'Unknown letter: "b". Allowed: qpzry9x8gf2tvdw0s3jn54khce6mua7l'

These errors occurred when trying to decode raw hex event IDs as bech32.
2025-10-19 23:49:12 +02:00
Gigi
de287c625b chore: remove relay.current.fyi from relay list
Removed 'wss://relay.current.fyi' from both api/article-og.ts and
src/config/relays.ts as this relay is no longer used.
2025-10-19 23:47:33 +02:00
Gigi
1424f6ebc5 debug: add console.log statements to debug mark-as-read reaction tracking
Added detailed logging throughout the kind:7 and kind:17 reaction
processing to understand:
- What reactions are being fetched
- Which ones have MARK_AS_READ_EMOJI
- Event ID extraction
- Article lookups
- Event ID to naddr mapping
- Final markedAsReadIds set

Check browser console when loading /me/reads to see the full flow.
2025-10-19 23:46:25 +02:00
Gigi
b0a368fc64 fix: properly handle kind:7 mark-as-read reactions with event ID to naddr mapping
Restored kind:7 reaction handling with proper implementation:
1. Fetch kind:7 reactions with MARK_AS_READ_EMOJI
2. Extract event IDs from #e tags
3. Fetch the referenced articles (kind:30023)
4. Build mapping of event IDs to nadrs
5. Add marked articles to markedAsReadIds using their nadrs

Now both kind:7 (Nostr articles) and kind:17 (URLs) mark-as-read
reactions are properly tracked and will appear in /me/reads/completed.

Added nip19 import for naddr encoding.
2025-10-19 23:44:56 +02:00
Gigi
6f8cf641b7 fix: correctly track mark-as-read reactions in readingProgressController
Fixed several issues:
1. Clear markedAsReadIds on reset() so it doesn't persist across logouts
2. Skip kind:7 reactions (events) as they require complex event ID to naddr mapping
3. Only process kind:17 reactions (URLs) which directly use URLs as identifiers
4. Correctly extract URL from #r tag instead of using emoji content

Now kind:17 mark-as-read reactions for external URLs are properly tracked.
These articles will appear in /me/reads/completed.
2025-10-19 23:42:22 +02:00
Gigi
23b4c3475f feat: track mark-as-read reactions in readingProgressController
Extended readingProgressController to also fetch and track mark-as-read
reactions (kind:7 and kind:17 with MARK_AS_READ_EMOJI) alongside reading
progress events.

Changes:
- Added markedAsReadIds Set to controller
- Query mark-as-read reactions in parallel with reading progress
- Added isMarkedAsRead() method to check if article is marked as read
- Updated Me.tsx to include markedAsRead status in ReadItems

Now /me/reads/completed shows:
- Articles with >= 95% reading progress
- Articles marked as read with the 📚 emoji
2025-10-19 23:33:22 +02:00
Gigi
5633dc640c refactor: simplify reads - use readingProgressController directly
Removed the complex readsController wrapper. Now /me/reads simply:
1. Uses readingProgressController (already loaded in App.tsx)
2. Converts progress map to ReadItems
3. Subscribes to progress updates

This is much simpler and DRY - no need for a separate controller.
Reading progress is already deduped and managed centrally.

Same approach as debug page - just use the data source directly.
2025-10-19 23:29:06 +02:00
Gigi
0f1dfa445a refactor: simplify reads loading - don't require bookmarks
Reads don't actually need bookmarks to load. Reading progress (kind:39802)
is independent and stands on its own. Bookmarks are just optional enrichment.

Changed:
- readsController.start() no longer takes bookmarks parameter
- Pass empty array to fetchAllReads instead
- Load reads immediately in App.tsx like highlights/writings
- No more circular dependency on bookmarks loading first

This is simpler and loads reading progress faster.
2025-10-19 23:26:00 +02:00
Gigi
ab5225de50 fix: emit all reading items not just articles
The onItem callback was filtering to only 'article' type items,
which excluded external URLs from reading progress. Now all items
(articles and external URLs) are emitted to readsController.

This fixes the empty reads list issue where reading progress exists
but wasn't being displayed.
2025-10-19 23:24:58 +02:00
Gigi
b89705cf43 feat: load reads centrally in App.tsx like bookmarks and highlights
- Import readsController in App.tsx
- Start readsController in the central useEffect when user logs in
- Pass bookmarks to readsController.start() for article lookups
- Simplify Me.tsx loadReadsTab to just mark tab as loaded
- Subscription to readsController in Me.tsx still streams updates to UI

This means:
- Reads load in the background automatically
- Data is available even before clicking the Reads tab
- Consistent with how bookmarks, highlights, and writings are loaded
- Non-blocking - readsController streams updates progressively
2025-10-19 23:23:16 +02:00
Gigi
740dd53299 fix: properly subscribe to readsController updates with useEffect
The loadReadsTab async function was trying to return cleanup functions,
which doesn't work in React. Moved the subscription logic to a separate
useEffect hook with empty dependency array so:
- Subscriptions are set up once on mount
- Cleanup happens properly on unmount
- readsController updates flow through to UI correctly

This fixes the empty reads list issue.
2025-10-19 23:21:12 +02:00
Gigi
eb61553c20 feat: create readsController following highlightsController pattern
- New src/services/readsController.ts manages all reading activity centrally
- Streams reading items as they arrive (progress, marks as read, bookmarks)
- Supports subscriptions via onReads() and onLoading() callbacks
- Tracks loading state and last synced timestamp per user
- Generation-based cancellation for logout/pubkey changes
- Deduplicates by article ID and sorts by reading activity
- Updated Me.tsx loadReadsTab to use readsController instead of calling fetchAllReads
- Provides same reactive, non-blocking UX as highlightsController
2025-10-19 23:19:46 +02:00
Gigi
8b708535ca fix: don't block UI while loading reads - stream updates as data arrives
Changed loadReadsTab to not await fetchAllReads. Instead:
- Start with empty state immediately
- Use onItem callback to stream updates as they're fetched
- Reading data flows in as it arrives (reading progress, marks as read, etc)
- UI doesn't block waiting for all article data to be fetched

Same pattern as debug page - provides responsive UI with progressive loading.
2025-10-19 23:17:40 +02:00
Gigi
f77761c002 feat: show all reading activity in /me/reads, not just bookmarks
Changed loadReadsTab to use fetchAllReads directly instead of deriveReadsFromBookmarks.
Now /me/reads shows ALL articles with any reading activity:
- Articles with reading progress (kind:39802)
- Articles marked as read (kind:7, kind:17 reactions)
- Articles with highlights
- Bookmarked articles

Previously only showed bookmarked articles and tried to enrich with reading data.
Now the reading data (progress, marks as read) is the primary source.
2025-10-19 23:15:53 +02:00
Gigi
b900666eb8 feat: add category breakdown to reading progress debug output
Shows counts of articles in each reading progress category:
- Unopened (0%)
- Started (0% < progress ≤ 10%)
- Reading (10% < progress ≤ 94%) - highlighted in green
- Completed (≥ 95%)

This helps understand why /me/reads/reading shows fewer articles than
the total reading progress events - most articles fall into other categories.
2025-10-19 23:11:38 +02:00
Gigi
2639c78957 feat: display both raw and deduplicated reading progress events
- Load raw events from queryEvents for transparency
- Load deduplicated results from readingProgressController in parallel
- Display raw events first, then deduplicated results below for comparison
- Helps debugging by showing all events plus the final processed state
2025-10-19 23:08:31 +02:00
Gigi
8320911bc9 refactor: use readingProgressController for deduplicated progress in debug
- Replace raw queryEvents with readingProgressController.start() for reading progress
- Controller already handles deduplication by article (d-tag) and keeps most recent
- Display deduplicated progress map below raw events for easy comparison
- Add progress percentage and visual progress bar for each article
- Add styling with blue background to distinguish deduplicated results
2025-10-19 23:07:32 +02:00
Gigi
00d6bd4c46 feat: add reading progress loading section to debug page
- Add state variables for reading progress events and mark-as-read reactions
- Implement handler to load all reading progress events (kind:39802) for logged-in user
- Implement handler to load all mark-as-read reactions (kind:7, kind:17) with MARK_AS_READ_EMOJI filter
- Add two new sections to debug page with buttons and results display
- Display event details including author, creation time, and relevant tags
- Include timing metrics for load operations
2025-10-19 23:02:15 +02:00
Gigi
cd377b6f26 docs: update CHANGELOG.md for v0.8.2 release
- Added reading progress indicator in compact cards
- Compact cards layout optimizations (reduced padding, row height, gaps)
- Reading progress bar styling (thinner, aligned with text)
- Fixed: Removed borders from compact bookmarks
2025-10-19 22:55:39 +02:00
Gigi
84b0339505 chore: bump version to 0.8.2 v0.8.2 2025-10-19 22:54:46 +02:00
Gigi
12fa1db0db style: adjust progress bar margin in compact cards
- Reduce left margin from 1.75rem to 1.5rem for better visual balance
2025-10-19 22:54:19 +02:00
Gigi
0919091f19 style: align reading progress bar with text in compact cards
- Add left margin of 1.75rem to progress bar to start where text begins
- Prevents progress bar from looking like a separator
- Creates visual association between progress indicator and the specific bookmark item
2025-10-19 22:53:49 +02:00
Gigi
e1c04b4e7f fix: align progress bar to start at title position
- Add padding-left to progress bar container to offset it to title position
- Remove margin from inner fill
- Progress bar now visually starts where the title starts, not at the icon
2025-10-19 22:52:32 +02:00
Gigi
b9642067a1 fix: use margin instead of padding for reading progress bar alignment
- Move left offset from outer container padding to inner progress fill margin
- Background bar now spans full width while progress fill starts at text position
- Creates cleaner visual alignment without distorting the bar appearance
2025-10-19 22:51:36 +02:00
Gigi
ceca37df08 style: align reading progress bar with title text in compact cards
- Add left padding (1.85rem) to progress bar to align with bookmark title
- Progress bar now starts at the same position as the text content
2025-10-19 22:50:48 +02:00
Gigi
dfdc5d0946 style: make reading progress bar thinner in compact cards
- Reduce reading progress bar height from 2px to 1px
- Creates a more subtle, minimal progress indicator for compact bookmarks
2025-10-19 22:49:46 +02:00
Gigi
3619cd2585 fix: remove borders from compact bookmarks in sidebar
- Add explicit CSS rule to remove border from compact bookmarks in .bookmarks-list
- Override the border styling from me.css that was applying to all .individual-bookmark elements
- Ensure compact cards remain borderless and transparent
2025-10-19 22:49:01 +02:00
Gigi
f93e52611e style: make compact cards even more compact
- Reduce padding from 0.5rem to 0.25rem vertically
- Reduce compact row height from 28px to 24px
- Reduce gap between compact cards from 0.5rem to 0.25rem
- Creates a tighter, more space-efficient list layout
2025-10-19 22:48:17 +02:00
Gigi
ecb81cb151 feat: show reading progress in compact cards in bookmarks sidebar
- Add reading progress state and subscription to BookmarkList component
- Create helper function to get reading progress for both articles (using naddr) and web bookmarks (using URL)
- Update CompactView to display reading progress indicator for all bookmark types
- Progress indicator now shows for any bookmark with reading data, not just articles
2025-10-19 22:46:34 +02:00
Gigi
adf73cb9d1 fix: resolve all linting and type errors
- Fix empty catch blocks by adding explanatory comments
- Remove unused variables or prefix with underscore
- Remove orphaned object literals from removed console.log statements
- Fix unnecessary dependency array entries
- Ensure all empty code blocks have comments to satisfy eslint no-empty rule
2025-10-19 22:41:35 +02:00
Gigi
4202807777 refactor: remove all console.log debug output 2025-10-19 22:35:45 +02:00
Gigi
1c21615103 chore: bump version to 0.8.1 v0.8.1 2025-10-19 22:31:06 +02:00