Commit Graph

195 Commits

Author SHA1 Message Date
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
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
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
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
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
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
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
c2d2bd8106 fix: prevent highlights from disappearing on external URLs
- Improve error handling in fetchHighlightsForUrl to prevent silent failures
- Remove redundant setHighlights call that was overwriting streamed highlights
- Add logging to help diagnose highlight fetching issues
- Isolate rebroadcast errors so they don't break highlight display
2025-10-15 19:56:07 +02:00
Gigi
0cf076b010 chore: change default paragraph alignment to justify 2025-10-15 17:45:10 +02:00
Gigi
e2c712033f feat: add paragraph alignment setting
- Add paragraphAlignment setting (left/justify) to UserSettings interface
- Add UI control with icon buttons in ReadingDisplaySettings
- Apply alignment via CSS variable to reader content and preview
- Default to left-aligned to maintain current behavior
- Keep headings always left-aligned for better readability
2025-10-15 17:43:31 +02:00
Gigi
401a8241bd fix: resolve lint and type errors
- Changed idToEvent from let to const (prefer-const)
- Fixed TypeScript type narrowing issue by using direct regex test instead of isHexId type guard
- Removed unused isHexId import

All lint and type checks now pass for src directory.
2025-10-15 16:09:46 +02:00
Gigi
2193a7a863 fix: properly handle AddressPointer bookmarks for long-form articles
The issue was that Primal bookmarks long-form articles using 'a' tags
(AddressPointer format: kind:pubkey:identifier) but our code was only
expecting EventPointer objects with 'id' properties.

Changes:
- Updated ApplesauceBookmarks interface to match actual applesauce types
- Added AddressPointer and EventPointer interfaces
- Rewrote processApplesauceBookmarks to handle all bookmark types:
  * notes (EventPointer) - regular notes
  * articles (AddressPointer) - long-form content (kind:30023)
  * hashtags (string[])
  * urls (string[])
- Updated bookmark hydration to query addressable events by coordinates
- Added logging to show hydration stats

This should fix the issue where Primal's Reads bookmarks weren't showing up.
2025-10-15 16:06:03 +02:00
Gigi
aee9f73316 debug: add detailed logging for bookmark event tags
Added logging to show:
- e and a tag counts for all events
- which events survived deduplication
- specific check for Primal reads list (kind:10003 with d='reads')
2025-10-15 15:59:56 +02:00
Gigi
aef7b4cea4 fix: include kind:30003 in default bookmark list detection
Previously, the dedupeNip51Events function was only looking for kind:10003
and kind:30001 when finding the default bookmark list. This excluded
kind:30003 events without a 'd' tag, which is what Primal uses for
bookmarks. Now kind:30003 is properly included in the filter.
2025-10-15 15:54:47 +02:00
Gigi
eaa590b8e2 feat: add support for bookmark sets (kind 30003)
- Add setName, setTitle, setDescription, and setImage fields to IndividualBookmark type
- Extract d tag and metadata from kind 30003 events in bookmark processing
- Create helper functions to group bookmarks by set and extract set metadata
- Display bookmark sets as separate sections in BookmarkList UI
- Maintain existing content-type categorization alongside bookmark sets
2025-10-15 15:25:33 +02:00
Gigi
29e351ba78 feat(bookmarks): tag sourceKind in collection for web and list/set items 2025-10-15 13:58:48 +02:00
Gigi
ca339ac0b2 refactor: remove all eslint-disable statements and fix underlying issues
- Replace @typescript-eslint/no-explicit-any with proper Filter type from nostr-tools/filter in dataFetch.ts and helpers.ts
- Replace @typescript-eslint/no-explicit-any with IAccount and AccountManager types from applesauce-accounts in hooks
- Replace @typescript-eslint/no-explicit-any with unknown type casts in App.tsx for keep-alive subscription
- Fix react-hooks/exhaustive-deps warnings by including all dependencies in useEffect hooks
- Remove unused _settings parameters in useImageCache.ts that were causing no-unused-vars warnings
2025-10-15 09:57:14 +02:00
Gigi
2939747ebf fix(lint): resolve all linting and type errors
- Remove unused imports (useRef, faExclamationCircle, getProfileUrl, Observable, UserSettings)
- Remove unused error state and setError calls in Explore and Me components
- Remove unused 'events' variable from exploreService and nostrverseService
- Remove unused '_relays' parameter from saveSettings
- Remove unused '_settings' parameter from publishEvent
- Update all callers of publishEvent and saveSettings to match new signatures
- Add eslint-disable comment for intentional dependency omission in Explore
- Update BookmarkList to use new pull-to-refresh library and RefreshIndicator
- All type checks and linting now pass
2025-10-15 09:42:56 +02:00
Gigi
3091ad7fd4 feat(write): add unified publishEvent service and refactor highlight and settings to use it 2025-10-15 09:29:54 +02:00
Gigi
5b7488295c refactor(fetch): migrate nostrverseService, bookmarkService, and libraryService to use queryEvents 2025-10-15 09:28:35 +02:00
Gigi
bea62ddc4b refactor(fetch): migrate exploreService and fetchHighlightsFromAuthors to use queryEvents 2025-10-15 09:26:33 +02:00
Gigi
02ec8dd936 feat(fetch): add unified queryEvents helper and stream contacts partials with extended timeout 2025-10-15 09:17:51 +02:00
Gigi
46a6d4fe0c chore: restore production thresholds (2100 sats / 69420 sats)
Removed testing values and restored proper production thresholds
2025-10-15 01:44:45 +02:00
Gigi
02c1b6b783 chore: temporarily lower thresholds for testing (2 sats / 21 sats)
- Lower supporter threshold from 2100 to 2 sats
- Lower whale threshold from 69420 to 21 sats
- Add TODO comment to restore production values
- For testing support page with smaller zaps
2025-10-15 01:25:39 +02:00
Gigi
0ca3771906 fix: improve zap receipt scanning with applesauce helpers and more relays
- Use isValidZap, getZapSender, getZapAmount from applesauce-core/helpers
- Add common zap relays (Mutiny, Alby) to improve coverage
- Add detailed logging to debug zap receipt fetching
- Remove custom extraction functions in favor of applesauce helpers
2025-10-15 01:04:17 +02:00
Gigi
6dab126f88 fix: resolve lint and type errors in support page implementation 2025-10-15 01:01:18 +02:00
Gigi
36897e7f15 feat: add zapReceiptService to fetch and aggregate kind:9735 receipts 2025-10-15 00:53:14 +02:00
Gigi
f18315be02 feat: export BORIS_PUBKEY for reuse in support page 2025-10-15 00:53:09 +02:00
Gigi
be045557b8 feat: add nostrverse content and visibility filters to explore page
- Add visibility filter state and UI (mine/friends/nostrverse toggles)
- Create nostrverseService to fetch public content from the entire network
- Fetch both friends content and nostrverse content in parallel
- Apply visibility filters to both highlights and blog posts
- Filter buttons match highlight sidebar styling
- Users can now discover content beyond their friend network
- Maintains performance with sensible limits (50 posts, 100 highlights)
2025-10-14 12:09:12 +02:00
Gigi
9aff889835 fix: correct profile fetching implementation and dependencies
- Use eventStore.add() directly instead of mapEventsToStore
- Use tap() operator to process and store events as they arrive
- Add eventStore and settings to useEffect dependencies
- Fixes TypeScript and ESLint errors
2025-10-14 12:00:52 +02:00
Gigi
420df1fbdd feat: fetch and cache author profiles in explore page
- Create profileService to fetch and cache kind:0 metadata
- Fetch profiles for all blog post authors on explore page
- Store profiles in event store for immediate access
- Rebroadcast profiles to local/all relays per user settings
- Fixes 'Unknown' author names by ensuring profiles are cached
- Uses mapEventsToStore to automatically populate event store
2025-10-14 11:59:28 +02:00
Gigi
b1f79e3844 fix: resolve type errors and remove unused code
- Remove unused handleHighlightDelete function
- Fix all TypeScript type errors by using correct Highlight properties
- Use created_at instead of timestamp
- Use content instead of text
- Use urlReference instead of url
- All lint checks and type checks now pass
2025-10-14 10:54:51 +02:00
Gigi
0aba54bd23 feat(explore): add highlights tab to explore page
- Create fetchHighlightsFromAuthors function for fetching highlights from multiple contacts
- Add tab structure to Explore page (Writings and Highlights tabs)
- Update explore cache to handle both blog posts and highlights
- Add /explore/highlights route
- Keep UI consistent with /me page tab structure
- Implement pull-to-refresh for both tabs
- Add proper caching and streaming for highlights
2025-10-14 10:45:23 +02:00
Gigi
689963c041 refactor(theme): change default light theme to sepia
- Update default from paper-white to sepia for warmer reading
- Midnight remains default for dark mode
- Sepia provides warm, eye-friendly tones for light mode
2025-10-14 10:00:21 +02:00
Gigi
129aced1a2 feat(theme): add color theme variants for light and dark modes
- Add darkColorTheme: black, midnight (default), charcoal
- Add lightColorTheme: paper-white (default), sepia, ivory
- Extend UserSettings with color theme fields
- Update ThemeSettings UI to show color options
- Add CSS variables for all color theme variants
- Sepia and Ivory have warm, reading-friendly palettes
- Black offers true black for OLED screens
- All color themes sync via Nostr (NIP-78)
2025-10-14 09:39:13 +02:00
Gigi
994d834a0b feat(theme): add CSS variable tokens and theme classes
- Define semantic color tokens (--color-bg, --color-text, etc.)
- Add .theme-dark, .theme-light, .theme-system CSS classes
- Create theme.ts utility for theme application
- Add early boot theme script to prevent FOUC
- Support system preference with live updates
2025-10-14 09:11:38 +02:00
Gigi
ec423cad80 feat(services): youtubeMetaService with 7d localStorage cache and ID extraction 2025-10-13 19:27:34 +02:00
Gigi
e09be543bc feat: add caching to /me page for faster loading
- Create meCache service to store highlights, bookmarks, and read articles
- Seed Me component from cache on load to avoid empty flash
- Show small spinner while refreshing if cached data is displayed
- Update cache when highlights are deleted
- Only show full loading screen if no cached data is available
- Improves perceived performance similar to /explore page
2025-10-13 16:50:43 +02:00
Gigi
5ac0e7ed87 fix: deduplicate article events in library to prevent showing duplicates 2025-10-13 12:15:16 +02:00
Gigi
e1a3ae4b4d feat: render library articles using BlogPostCard component for consistency 2025-10-13 12:13:12 +02:00
Gigi
0d8a3576a6 feat: add tabbed layout to /me page with Highlights, Reading List, and Library tabs 2025-10-13 10:35:14 +02:00
Gigi
6c0a2439ad feat: instant mark-as-read with checkmark animation and read status checking
- Add functions to check if article/URL was already marked as read via NIP-25 reactions
- Make mark-as-read action instant with fire-and-forget publishing
- Add checkmark icon animation when marking as read
- Display read status on load by querying kind:7 (nostr events) and kind:17 (websites) reactions
- Add green styling for already-read state
- Button shows checkmark and is disabled when article is already marked as read
2025-10-13 10:17:16 +02:00
Gigi
079501337c fix: filter out invalid bookmarks without IDs
- Skip bookmarks that don't have a valid ID instead of generating temporary IDs
- Use bookmark's original created_at timestamp for added_at instead of Date.now()
- Fixes issue where first 2 bookmarks always showed 'Now' timestamp with no content
2025-10-13 08:50:29 +02:00
Gigi
b8b9f82d91 ux(explore): preserve posts across navigations; seed from cache; merge streamed + final 2025-10-12 23:30:56 +02:00
Gigi
b3fc9bb5c3 ux(bookmarks): avoid clearing list when no new events; decouple refetch from route changes 2025-10-12 23:26:18 +02:00
Gigi
496d1df404 perf(parallel): run local+remote fetches concurrently across services; stream+dedupe 2025-10-12 23:13:26 +02:00
Gigi
ea1046fe13 perf(local-first): always follow up with remote for articles and titles 2025-10-12 23:00:23 +02:00
Gigi
6d58d6e7f3 fix(highlights): ensure nostrverse fetch merges remote results after local for article/url 2025-10-12 22:58:25 +02:00
Gigi
e1420140d1 chore(lint): fix eslint and typescript issues; no rule changes 2025-10-12 22:55:46 +02:00