Commit Graph

1707 Commits

Author SHA1 Message Date
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
Gigi
732070e89b fix: re-derive reads/links when bookmarks change
- Add bookmarks to useEffect dependencies that load tab data
- Reads tab now updates when bookmarks are loaded/updated
- Fixes 'No articles ready yet' disappearing when switching tabs
- Ensures reads are always derived from current bookmark state
- Re-renders Reads tab whenever bookmarks change
2025-10-19 22:29:02 +02:00
Gigi
d9a00dd157 fix: merge reading progress from controller into reads/links before filtering
- Enrich reads and links arrays with reading progress from readingProgressMap
- Use item.id to lookup progress for articles
- Use item.url to lookup progress for links
- Now 'started' and 'reading' filters show correct articles
- Filters respond in real-time as reading progress updates from controller
2025-10-19 22:25:55 +02:00
Gigi
103be75f6e feat: auto-load reading progress on login and app start
- Add readingProgressController.start() to App.tsx
- Follows same pattern as highlightsController and writingsController
- Checks isLoadedFor(pubkey) to prevent duplicate loading
- Automatically fetches reading progress when user logs in
- Loads progress from cache first, then streams from relays
- Reading progress now available immediately for filters and indicators
2025-10-19 22:23:03 +02:00
Gigi
8dd4e358b4 fix: normalize highlight article references to naddr format for proper matching
- Convert coordinate-format eventReferences (30023:pubkey:identifier) to naddr
- ReadItems use naddr format for IDs, but highlights store coordinates
- Properly match highlights to articles by normalizing both formats
- Fixes 'highlighted' filter showing no results
- Handles conversion errors gracefully by falling back to original format
2025-10-19 22:21:43 +02:00
Gigi
2e8dfaee09 refactor: reorder reading progress filters - highlighted before completed
- Move highlighted filter before completed in button order
- Reading filters now appear in logical order:
  All → Unopened → Started → Reading → Highlighted → Completed
2025-10-19 22:20:31 +02:00
Gigi
db3084b373 fix: use ES6 import instead of require in helpers.ts
- Replace require() call with ES6 import for READING_PROGRESS constant
- Fixes linter error: 'require' is not defined (no-undef)
- All linter checks now pass with no warnings or errors
2025-10-19 22:19:06 +02:00
Gigi
83e4a2ad4c refactor: rename Amethyst bookmark sections to simpler names
- Rename 'Amethyst Lists' to 'My Lists'
- Rename 'Amethyst Private' to 'Private Lists'
- Clearer and more intuitive names without referencing the Amethyst client
- Applied in both Me.tsx and BookmarkList.tsx

These sections contain kind:30001 bookmarks (replaceable list events).
2025-10-19 22:18:16 +02:00
Gigi
c1d23fac7b feat: show reading progress in compact and card view bookmarks
- Add readingProgress prop to BookmarkItem component
- Display reading progress in CompactView with 2px indicator
- Display reading progress in CardView with 3px indicator
- Progress color matches main app: blue (reading), green (completed), neutral (started)
- Add getBookmarkReadingProgress helper in Me.tsx
- Show progress only for kind:30023 articles with progress > 0
- Reading progress now visible across all bookmark view modes
2025-10-19 22:17:35 +02:00
Gigi
de32310801 feat: add highlights filter button to reading progress filters
- Add 'highlighted' filter type to ReadingProgressFilterType
- New filter button with yellow highlighter icon
- Filter shows only articles that have highlights
- Highlights filter checks both eventReference and urlReference tags
- Color-coded: green for completed, yellow for highlighted, blue for others
- Applies to reads and links tabs in /me page
2025-10-19 22:15:13 +02:00
Gigi
5c82dff8df feat: only track reading progress for articles above minimum length
- Add MIN_CONTENT_LENGTH constant (1000 chars ≈ 150 words) to config/kinds
- Create shouldTrackReadingProgress helper to validate content length
- Strip HTML tags when calculating character count
- Only save reading progress for articles meeting the threshold
- Log when content is too short to track

This prevents noisy tracking of very short articles or excerpts.
2025-10-19 22:13:37 +02:00
Gigi
abe2d6528a feat: add setting to hide bookmarks missing creation date
- Add hideBookmarksWithoutCreationDate to UserSettings
- New checkbox in Layout & Behavior settings
- Bookmarks without valid creation dates shown as 'Now'
- Setting disabled by default to maintain current behavior
2025-10-19 22:11:47 +02:00
Gigi
8b56fe3d6e ux: update Flight Mode notification text to say 'Local relays only' 2025-10-19 22:10:32 +02:00
Gigi
bdce7c9358 docs: update CHANGELOG.md for v0.8.0 release 2025-10-19 22:09:56 +02:00
Gigi
81a4ae392f bump: release version 0.8.0 v0.8.0 2025-10-19 22:09:13 +02:00
Gigi
6e438b8ee2 Merge pull request #21 from dergigi/reading-progress-nip
feat: implement NIP-85 reading progress tracking
2025-10-19 22:08:04 +02:00
Gigi
31974e7271 feat(reading): 2s completion hold at 100% + reliable auto mark-as-read
- Add completionHoldMs (default 2000ms) to useReadingPosition
- Start hold timer when position hits 100%; cancel if user scrolls up
- Fallback to threshold completion when configured
- Clears timers on unmount/disable
2025-10-19 16:17:17 +02:00
Gigi
676be1a932 feat: make reading position sync default-on in runtime paths
- Treat undefined as enabled in ContentPanel (only false disables)
- Keeps DEFAULT_SETTINGS at true; ensures consistent behavior even for users without the new setting persisted yet
2025-10-19 16:15:43 +02:00
Gigi
9883f2eb1a chore(settings): tweak label for auto mark-as-read (remove animation note) 2025-10-19 16:13:56 +02:00
Gigi
87e46be86f feat(settings): restore 'auto mark as read at 100%' option
- Added autoMarkAsReadOnCompletion to default settings (disabled by default)
- Added toggle in Layout & Behavior section
- Existing ContentPanel logic already hooks into this to trigger animation & mark-as-read
2025-10-19 16:07:59 +02:00
Gigi
b745a92a7e feat: allow saving 0% reading position and initial save
- Remove low-position guard; allow 0% saves
- One-time initial save even without significant change
- Always allow immediate save regardless of position
- Fix linter empty-catch warnings in readingProgressController
2025-10-19 16:03:34 +02:00
Gigi
5a79da4024 feat: persist reading progress in localStorage per pubkey
- Seed controller state from cache on start for instant display after refresh
- Persist updated progress map after processing events
- Keeps progress visible even without immediate relay responses
2025-10-19 15:59:01 +02:00
Gigi
a7d05a29f5 feat: process local reading progress via eventStore.timeline()
- Subscribe to timeline for immediate local events and reactive updates
- Clean up timeline subscription on reset/start to avoid leaks
- Keep relay sync for background augmentation
- Should populate progress map even without relay roundtrip
2025-10-19 12:29:44 +02:00
Gigi
0740d53d37 fix: resolve all linter warnings
- Add proper types (Filter, NostrEvent) to readingProgressController
- Add eslint-disable comment for position dependency in useReadingPosition
  (position is derived from scroll and including it would cause infinite re-renders)
- All lint warnings resolved
- TypeScript type checks pass
2025-10-19 12:27:19 +02:00
Gigi
914738abb4 fix: force full sync when map is empty
- If currentProgressMap is empty, do a full sync (no 'since' filter)
- This ensures first load gets all events, not just recent ones
- Incremental sync only happens when we already have data
- This was the bug: lastSynced was preventing initial load of events
2025-10-19 12:18:46 +02:00
Gigi
4fac5f42c9 fix: remove broken timeline subscription, rely on queryEvents
- Timeline subscription is async and emits empty array first
- queryEvents already checks local store then relays
- Simpler and actually works correctly
- This is how all other controllers work (highlights, bookmarks, etc.)
2025-10-19 12:17:38 +02:00
Gigi
16b3668e73 debug: add logs to trace why events aren't processed
- Log sample event to see format
- Log map size after processEvents to see if it worked
- This will show if processEvents is failing silently
2025-10-19 12:13:45 +02:00
Gigi
f3a83256a8 debug: improve timeline subscription and add more logs
- Capture events from timeline before unsubscribing
- Add log to show when timeline emits
- Add log after unsubscribe to show what we got
- This will help debug why processEvents isn't being called
2025-10-19 12:10:53 +02:00
Gigi
0e98ddeef4 fix: use eventStore.timeline() to query local events
- Subscribe to timeline to get initial cached events
- Unsubscribe immediately after reading initial value
- This works with IEventStore interface correctly
2025-10-19 12:04:49 +02:00
Gigi
1ba375e93e fix: load reading progress from event store first (non-blocking)
- Query local event store immediately for instant display
- Then augment with relay data in background
- This matches how bookmarks work: local-first, then sync
- Events saved locally now appear immediately without waiting for relay propagation
2025-10-19 12:03:36 +02:00
Gigi
5d14d25d0e debug: add detailed logging to Profile component
- Show initial map size and updates in Profile
- Log lookups with map contents in Profile
- Helps debug reading progress on profile pages
2025-10-19 12:02:22 +02:00
Gigi
616038a23a debug: reduce log spam and show map size in lookups
- Only log when progress found or map is empty
- Show map size to quickly diagnose empty map issue
- Show first 3 map keys as sample instead of all
2025-10-19 11:59:37 +02:00
Gigi
14fce2c3dc debug: add detailed naddr comparison logs
- 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
2025-10-19 11:56:27 +02:00
Gigi
7c511de474 feat: enable reading position sync by default
- Changed syncReadingPosition default from false to true in Settings.tsx
- Users can still disable it in settings if they prefer
- This ensures reading progress tracking works out of the box
2025-10-19 11:52:05 +02:00
Gigi
3a10ac8691 debug: add logs to show why reading position saves are skipped
- Log when scheduleSave returns early (syncEnabled false, no onSave callback)
- Log when position is too low (<5%)
- Log when change is not significant enough (<1%)
- Log ContentPanel sync status (enabled, settings, requirements)
- This will help diagnose why no events are being created
2025-10-19 11:41:38 +02:00
Gigi
205879f948 debug: add comprehensive logging for reading position calculation and event publishing
- Add logs in useReadingPosition: scroll position calculation (throttled to 5% changes)
- Add logs for scheduling and triggering auto-save
- Add detailed logs in ContentPanel handleSavePosition
- Add logs in saveReadingPosition: event creation, signing, publishing
- Add logs in publishEvent: event store addition, relay status, publishing
- All logs prefixed with [progress] for easy filtering
- Shows complete flow from scroll → calculate → save → create event → publish to relays
2025-10-19 11:39:25 +02:00
Gigi
bff43f4a28 debug: add comprehensive [progress] logging throughout reading progress flow
- 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
2025-10-19 11:30:57 +02:00
Gigi
2a7fffd594 fix: remove invalid eventStore.list() call in reading progress controller
- EventStore doesn't have a list() method
- Follow same pattern as highlightsController and just fetch from relays
- Fixes TypeError: eventStore.list is not a function
2025-10-19 11:18:21 +02:00
Gigi
50a4161e16 feat: reset reading progress controller on logout
- Add readingProgressController.reset() to handleLogout in App.tsx
- Ensures reading progress data is cleared when user logs out
- Consistent with other controllers (bookmarks, contacts, highlights)
2025-10-19 11:08:33 +02:00
Gigi
5fd8976097 refactor: create centralized reading progress controller
- 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
2025-10-19 11:06:57 +02:00
Gigi
80b26abff2 feat: add reading progress indicators to blog post cards
- 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%+)
2025-10-19 11:02:20 +02:00
Gigi
c0638851c6 docs: simplify NIP-85 to match NIP-84 style and length
- Remove verbose rationale section
- Remove excessive querying examples
- Remove privacy considerations (obvious)
- Remove implementation notes fluff
- Remove references section
- Keep only essential: format, tags, content, examples
- Match NIP-84's concise, to-the-point style

From 190 lines down to ~75 lines - much more readable
2025-10-19 10:54:31 +02:00
Gigi
9b6b14cfe8 refactor: remove client tag from reading progress events
- Remove 'client' tag from NIP-85 specification
- Remove 'client' tag from code implementation
- Align with Nostr principles of client-agnostic data
- Follow NIP-84 pattern which doesn't include client tags

Events should be client-agnostic and not include branding/tracking.
2025-10-19 10:46:44 +02:00
Gigi
b6ad62a3ab refactor: rename to NIP-85 (kind 39802 for reading progress)
- Rename NIP-39802.md to NIP-85.md
- Update all references from NIP-39802 to NIP-85 in code comments
- Add Table of Contents to NIP document
- Update kinds.ts to reference NIP-85 and NIP-84 (highlights)
- Maintain kind number 39802 for the event type

NIP-85 is the specification number, 39802 is the event kind number.
2025-10-19 10:41:02 +02:00
Gigi
85d87bac29 docs: improve NIP-39802 with URL cleaning guidance from NIP-84
- Add recommendation to clean URLs from tracking parameters
- Add URL Handling subsection with best practices
- Ensure same article from different sources maps to same progress
- Inspired by NIP-84 (Highlights) URL handling guidelines
2025-10-19 10:38:28 +02:00
Gigi
3b31eceeab feat: improve reading progress with validation and auto-mark
- Add autoMarkAsReadOnCompletion setting (opt-in, default: false)
- Implement auto-mark as read when reaching 95%+ completion
- Add validation for progress bounds (0-1) per NIP-39802 spec
- Align completion threshold to 95% to match filter behavior
- Skip invalid progress events with warning log

Improvements ensure consistency between completion detection and
filtering, while adding safety validation per the NIP spec.
2025-10-19 10:34:53 +02:00
Gigi
442c138d6a refactor: simplify NIP-39802 implementation - remove migration complexity
- Remove dual-write logic: only write kind 39802
- Remove legacy kind 30078 read fallback
- Remove migration settings flags (useReadingProgressKind, writeLegacyReadingPosition)
- Simplify readingPositionService: single write/read path
- Remove processReadingPositions() legacy processor
- Update readsService and linksService to only query kind 39802
- Simplify NIP-39802 spec: remove migration section
- Delete READING_PROGRESS_MIGRATION.md (not needed for unreleased app)
- Clean up imports and comments

No backward compatibility needed since app hasn't been released yet.
2025-10-19 10:14:37 +02:00