Commit Graph

1301 Commits

Author SHA1 Message Date
Gigi
fddf79e0c6 feat: add named kind constants, streaming updates, and fix reads/links tabs
- Create src/config/kinds.ts with named Nostr kind constants
- Add streaming support to fetchAllReads and fetchLinks with onItem callbacks
- Update all services to use KINDS constants instead of magic numbers
- Add mergeReadItem utility for DRY state management
- Add fallbackTitleFromUrl for external links without titles
- Relax validation to allow external items without titles
- Update Me.tsx to use streaming with Map-based state for reads/links
- Fix refresh to merge new data instead of clearing state
- Fix empty states for Reads and Links tabs (no more infinite skeletons)
- Services updated: readsService, linksService, libraryService, bookmarkService, exploreService, highlights/fetchByAuthor
2025-10-16 08:27:10 +02:00
Gigi
e6876d141f fix: show skeletons during initial tab load for reads/links 2025-10-16 01:43:36 +02:00
Gigi
5bb81b3c22 fix: always show skeletons for reads/links when no data
Removed empty state messages like "No articles in your reads" and
"No links yet" - now just show loading skeletons until data arrives.

This is simpler and prevents showing empty states while data is still
being fetched in the background.

Users will only see:
- Skeletons when no data (loading or truly empty)
- "No articles/links match this filter" when filtered out
- Actual content when data is available
2025-10-16 01:40:37 +02:00
Gigi
1e8e58fa05 fix: show loading skeletons correctly for reads and links tabs
The bug was that showSkeletons checked if ANY tab had data, so if you
had highlights or bookmarks, it would never show skeletons for reads/links
even while they were still loading.

Fix: Each tab now checks its own loading state (loading && tabData.length === 0)
instead of using the shared showSkeletons variable.

This makes the logic simple and clear:
1. If loading AND no data → show skeletons
2. If not loading AND no data → show empty state
3. If has data but filtered out → show no match message
4. Otherwise → show content
2025-10-16 01:39:03 +02:00
Gigi
f44e36e4bf refactor: make code more DRY by extracting shared utilities
- Create readingProgressUtils.ts with filterByReadingProgress function
- Create readingDataProcessor.ts with shared processing functions:
  - processReadingPositions
  - processMarkedAsRead
  - filterValidItems
  - sortByReadingActivity
- Refactor readsService.ts to use shared utilities
- Refactor linksService.ts to use shared utilities
- Eliminate 100+ lines of duplicated code
- Simplify Me.tsx filter logic to 2 lines

Benefits:
- Single source of truth for reading progress filtering
- Easier to maintain and modify
- Less code duplication across services
- More testable with isolated utility functions
2025-10-16 01:36:28 +02:00
Gigi
11c7564f8c feat: split Reads tab into Reads and Links
- Reads: Only Nostr-native articles (kind:30023)
- Links: Only external URLs with reading progress
- Create linksService.ts for fetching external URL links
- Update readsService to filter only Nostr articles
- Add Links tab between Reads and Writings with same filtering
- Add /me/links route
- Update meCache to include links field
- Both tabs support reading progress filters
- Lazy loading for both tabs

This provides clear separation between native Nostr content and external web links.
2025-10-16 01:33:04 +02:00
Gigi
a064376bd8 fix: filter out 'Untitled' items from Reads tab
- Exclude Nostr articles without event data (can't fetch title)
- Exclude external URLs without proper titles
- Prevents cluttering Reads with items that have no meaningful title
- Only shows items we can properly identify and display
2025-10-16 01:25:31 +02:00
Gigi
292e8e9bda fix: only show external URLs in Reads if they have reading progress
- External URLs with 0% progress are now filtered out
- External URLs only appear if readingProgress > 0 OR marked as read
- Nostr articles still show even at 0% (bookmarked articles)
- Keeps Reads tab focused on actual reading activity for external links
2025-10-16 01:24:50 +02:00
Gigi
951a3699ca fix: replace spinners with skeleton placeholders in Me tabs
- Replace spinner in highlights tab with 'No highlights yet' message
- Replace spinner in reading-list tab with 'No bookmarks yet' message
- Only show these messages when loading is complete and arrays are empty
- Remove unused faSpinner import
- Consistent with skeleton placeholder pattern used elsewhere
2025-10-16 01:21:31 +02:00
Gigi
860ec70b1c feat: implement lazy loading for Me component tabs
- Add loadedTabs state to track which tabs have been loaded
- Create tab-specific loading functions (loadHighlightsTab, loadWritingsTab, loadReadingListTab, loadReadsTab)
- Only load data for active tab on mount and tab switches
- Show cached data immediately, refresh in background when revisiting tabs
- Update pull-to-refresh to only reload the active tab
- Show loading skeletons only on first load of each tab
- Works for both /me (own profile) and /p/ (other profiles)

This reduces initial load time from 30+ seconds to 2-5 seconds by only fetching data for the active tab.
2025-10-16 01:19:06 +02:00
Gigi
2b69c72939 refactor: simplify loading state to use unified logic
- Remove separate loadingReads state
- Keep single loading state true until ALL data is loaded
- Matches existing pattern used in other tabs
- Keeps code DRY and simple
2025-10-16 01:08:56 +02:00
Gigi
b98d774cbf fix: filter out reads without timestamps
- Exclude items without readingTimestamp or markedAt from reads
- Prevents 'Just Now' items from appearing in the reads list
- Only show reads with valid activity timestamps
2025-10-16 01:06:27 +02:00
Gigi
8972571a18 fix: keep showing skeletons while reads are loading
- Add separate loadingReads state to track reads fetching
- Show skeletons during the entire reads loading period
- Set loading=false after public data (highlights/writings) completes
- Prevents showing 'No articles match this filter' while reads are being fetched
2025-10-16 01:05:42 +02:00
Gigi
ab5d5dca58 debug: add logging to reads filtering 2025-10-16 00:59:28 +02:00
Gigi
e383356af1 feat: rename Archive to Reads and expand functionality
- Create new readsService to aggregate all read content from multiple sources
- Include bookmarked articles, reading progress tracked articles, and manually marked-as-read items
- Update Me component to use new reads service
- Update routes from /me/archive to /me/reads
- Update meCache to use ReadItem[] instead of BlogPostPreview[]
- Update filter logic to use actual reading progress data
- Support both Nostr-native articles and external URLs in reads
- Fetch and display article metadata from multiple sources
- Sort by most recent reading activity
2025-10-16 00:45:16 +02:00
Gigi
165d10c49b feat: split 'To read' filter into 'Unopened' and 'Started'
- Add 'unopened' filter (no progress, 0%) - uses fa-envelope icon
- Add 'started' filter (0-10% progress) - uses fa-envelope-open icon
- Remove 'to-read' filter
- Use classic/regular variant for envelope icons
- Update filter logic in BookmarkList and Me components
- New filter ranges:
  - Unopened: 0% (never opened)
  - Started: 0-10% (opened but not read far)
  - Reading: 11-94%
  - Completed: 95-100%
2025-10-16 00:13:34 +02:00
Gigi
e0869c436b fix: adjust 'Reading' filter to 11-94% range
- Change 'reading' filter from 10-95% to 11-94%
- Creates clearer boundaries between filters:
  - To read: 0-10%
  - Reading: 11-94%
  - Completed: 95-100%
2025-10-16 00:10:20 +02:00
Gigi
95432fc276 fix: reading position filters now work correctly in bookmarks
- 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
2025-10-15 23:54:44 +02:00
Gigi
1982d25fa8 feat: add fancy animation to Mark as Read button
- Icon spins 360° with bounce effect (scale up during spin)
- Button background changes to vibrant green gradient (#10b981)
- Green pulsing box-shadow effect on activation
- Button scales up slightly on click for emphasis
- Holds green state for 1.5 seconds
- Smoothly fades to gray after animation
- Final state is gray button to indicate marked status
- Uses cubic-bezier easing for modern, smooth feel
- Total animation duration: 2.5 seconds
- Prevents interaction during animation
2025-10-15 23:39:14 +02:00
Gigi
2fc64b6028 feat: change 'To read' filter to show 0-10% progress
- Update 'to-read' filter range from 0-5% to 0-10%
- Update 'reading' filter to start at 10% instead of 5%
- Adjust filter comments to reflect new ranges
2025-10-15 23:37:59 +02:00
Gigi
6e8686a49d feat: treat marked-as-read articles as 100% progress
- 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
2025-10-15 23:36:05 +02:00
Gigi
fd5ce80a06 feat: add auto-mark as read at 100% reading progress
- Add autoMarkAsReadAt100 setting (default: false)
- Add checkbox in Layout & Behavior settings
- Automatically mark article as read after 2 seconds at 100% progress
- Trigger same animation as manual mark as read button
- Move isNostrArticle computation earlier for useCallback deps
- Move handleMarkAsRead to useCallback for use in auto-mark effect
2025-10-15 23:28:50 +02:00
Gigi
ac4185e2cc feat: merge 'Completed' and 'Marked as Read' filters into one
- Remove 'marked' filter type from ReadingProgressFilterType
- Update ReadingProgressFilters component to show only 4 filters
- Keep checkmark icon for unified 'Completed' filter
- Completed filter now shows both:
  - Articles with 95%+ reading progress
  - Articles manually marked as read (no position data or 0%)
- Remove unused faBooks icon import
- Update filter logic in BookmarkList and Me components
2025-10-15 23:22:40 +02:00
Gigi
9217077283 fix: replace spinners with skeletons during refresh in archive/writings tabs
- Changed spinner to empty state message only when not loading
- During refresh, keeps showing cached content or skeletons
- Archive: shows 'No articles in your archive' only when done loading
- Writings: shows 'No articles written yet' only when done loading
- Prevents jarring transition from skeletons to spinner during refresh
2025-10-15 23:20:54 +02:00
Gigi
b7c14b5c7c fix: restore top padding to reading progress filters
- Remove padding-top: 0 override
- Now has equal spacing top and bottom (0.5rem)
2025-10-15 23:18:31 +02:00
Gigi
9b3cc41770 refactor: rename ArchiveFilters to ReadingProgressFilters
- More accurate naming: filters are based on reading progress/position
- Renamed component: ArchiveFilters -> ReadingProgressFilters
- Renamed type: ArchiveFilterType -> ReadingProgressFilterType
- Renamed variables: archiveFilter -> readingProgressFilter
- Renamed CSS class: archive-filters-wrapper -> reading-progress-filters-wrapper
- Updated all imports and references in BookmarkList and Me components
- Updated comments to reflect reading progress filtering
2025-10-15 23:17:55 +02:00
Gigi
4c4bd2214c feat: add top border to archive filters in bookmarks sidebar
- Matches the style of bookmark type filters at top
- Visually separates archive filters from bookmarks content
2025-10-15 23:14:56 +02:00
Gigi
93c31650f4 fix: remove double border between archive filters and view controls
- Add archive-filters-wrapper class
- Remove border-bottom from bookmark-filters in wrapper
- Prevents double border (bookmark-filters border-bottom + view-mode-controls border-top)
2025-10-15 23:14:20 +02:00
Gigi
7f0d99fc29 fix: remove duplicate border between archive filters and view controls
- Remove borderTop from archive filters div
- Keep only the border from view-mode-controls CSS
2025-10-15 23:12:26 +02:00
Gigi
eb6dbe1644 feat: add archive filters to bookmarks sidebar
- Add ArchiveFilters component to bookmarks sidebar
- Filter buttons shown above view-mode-controls row
- Filters: All, To Read (0-5%), Reading (5-95%), Completed (95%+), Marked
- Only shown when kind:30023 articles are present
- Filters only apply to kind:30023 articles
- Other bookmark types (videos, notes, web) remain visible
2025-10-15 23:10:31 +02:00
Gigi
474da25f77 fix: add autoScrollToPosition to useEffect dependency array
- Fixes react-hooks/exhaustive-deps warning
- Ensures effect reruns when auto-scroll setting changes
2025-10-15 23:08:21 +02:00
Gigi
02eaa1c8f8 feat: show reading progress in Explore and Bookmarks sidebar
- 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
2025-10-15 23:07:18 +02:00
Gigi
8800791723 feat: add auto-scroll to reading position setting
- Add autoScrollToPosition setting (default: true)
- Add checkbox in Layout & Behavior settings
- Only auto-scroll when setting is enabled
- Allows users to disable auto-scrolling while keeping sync enabled
2025-10-15 22:53:47 +02:00
Gigi
6758b9678b fix: update 'To Read' filter to show 0-5% progress articles
- Filter now shows articles with 0-5% reading progress
- Excludes manually marked as read articles (those without position data)
- Updates comment to reflect new logic
2025-10-15 22:51:40 +02:00
Gigi
63f58e010f feat: use classic/regular bookmark icon for To Read filter
- Change from solid bookmark to regular (outline) bookmark icon
- Matches classic FontAwesome bookmark style
2025-10-15 22:46:15 +02:00
Gigi
d0b814e39d fix: update Archive filter icons for consistency
- Change 'All' icon to asterisk (*) to match Bookmarks filter
- Change 'Marked as Read' icon to faBooks (custom icon)
- Maintains consistent iconography across filter types
2025-10-15 22:40:52 +02:00
Gigi
f4a227e40a fix: improve reading position calculation to reach 100%
- Add 5px threshold to detect when scrolled to bottom
- Set position to exactly 1.0 (100%) when within 5px of bottom
- Remove upper limit on saving positions (now saves 100% completion)
- Always save when reaching 100% completion (important milestone)
- Don't restore position for completed articles (100%), start from top
- Better handling of edge cases in position detection
- Matches ReadingProgressIndicator calculation logic
2025-10-15 22:39:51 +02:00
Gigi
6ef0a6dd71 refactor: match ArchiveFilters styling to BookmarkFilters
- Use same CSS classes (filter-btn) as BookmarkFilters
- Show icons only, no text labels for consistency
- Add title and aria-label for accessibility
- Keep code DRY by following established pattern
2025-10-15 22:35:45 +02:00
Gigi
5502d71ac4 feat: add filter buttons to Archive tab
- Create ArchiveFilters component with 5 filter options
- All: Show all archived articles
- To Read: Articles with 0% progress (not started)
- Reading: Articles with progress between 0-95%
- Completed: Articles with 95%+ reading progress
- Marked: Manually marked as read (no position data)
- Filter logic based on reading position data
- Show empty state when no articles match filter
- Matches BookmarkFilters styling and UX pattern
2025-10-15 22:30:44 +02:00
Gigi
5e1146b015 fix: position reading progress bar as dividing line in cards
- Move progress indicator between summary and meta sections
- Replace the border-top dividing line with progress bar
- Show 3px progress bar when reading position exists
- Show 1px gray divider when no progress (maintains original look)
- Remove absolute positioning from bottom of card
- Remove border-top from meta section to avoid double lines
2025-10-15 22:26:48 +02:00
Gigi
8f89165711 debug: add comprehensive logging for reading position sync
- Add detailed console logs with emoji prefixes for easy filtering
- Log save/load operations in readingPositionService
- Log position restore in ContentPanel with requirements check
- Log Archive tab position loading with article details
- All logs prefixed with component/service name for clarity
- Log shows position percentages, identifiers, and timestamps
- Helps debug why positions may not be showing or syncing
2025-10-15 22:23:40 +02:00
Gigi
674634326f feat: add visual reading progress indicator to archive cards
- Display reading position as a horizontal progress bar at bottom of blog post cards
- Use blue (#6366f1) for progress <95%, green (#10b981) for >=95% complete
- Load reading positions for all articles in Archive tab
- Progress bar fills from left to right showing how much has been read
- Only shown when reading progress exists and is >0%
- Smooth transition animations on progress updates
2025-10-15 22:19:18 +02:00
Gigi
30eaec5770 refactor: remove redundant handleHighlightClick from Explore
- HighlightItem now handles navigation internally
- Remove duplicate navigation logic from Explore component
- Simplifies code and ensures consistent behavior across all highlight displays
2025-10-15 22:13:14 +02:00
Gigi
0ff3c864a9 feat: add click-to-open article navigation on highlights
- Click on highlights in /me/highlights or /p/:npub pages to open referenced article
- Parse eventReference to detect kind:30023 articles and navigate to /a/{naddr}
- Fall back to urlReference for external URLs, navigate to /r/{url}
- Maintain backward compatibility with existing onHighlightClick prop
- Show pointer cursor when highlight has navigable reference
2025-10-15 22:12:03 +02:00
Gigi
ab2ca1f5e7 fix: remove unused IEventStore import in ContentPanel 2025-10-15 22:09:58 +02:00
Gigi
cf2d227f61 feat: add reading position sync across devices using Nostr Kind 30078
- Create readingPositionService.ts for save/load operations
- Add syncReadingPosition setting (opt-in via Settings > Layout & Behavior)
- Enhance useReadingPosition hook with auto-save (debounced 5s) and immediate save on navigation
- Integrate position restore in ContentPanel with smooth scroll to saved position
- Support both Nostr articles (naddr) and external URLs
- Reading positions stored privately to user's relays
- Auto-save excludes first 5% and last 5% of content to avoid noise
- Position automatically restored when returning to article
2025-10-15 22:08:12 +02:00
Gigi
2c9e6cc54e docs: update CHANGELOG.md for v0.6.20 2025-10-15 21:54:02 +02:00
Gigi
8da0a06711 chore: bump version to 0.6.20 v0.6.20 2025-10-15 21:53:06 +02:00
Gigi
be8d857223 Merge pull request #12 from dergigi/bookmark-filter-buttons
Add bookmark filter buttons by content type
2025-10-15 21:52:37 +02:00
Gigi
d50bcd700e fix(ui): make highlight button fixed to viewport 2025-10-15 21:51:24 +02:00