2508 Commits

Author SHA1 Message Date
Gigi
589ac17114 fix: prevent double-processing of markdown to avoid nested links
Added check to detect if markdown has already been processed by looking
for our internal routes (/a/naddr1... or /p/npub1...) in markdown links.
If found, skip re-processing to prevent nested markdown link issues.

This addresses timing issues where markdown might be processed multiple
times, causing nostr URIs that were already converted to links to be
processed again, creating nested/duplicated markdown link structures.
2025-11-01 00:22:15 +01:00
Gigi
8d3510947c fix: add HTTP URL detection to prevent processing nostr URIs in URLs
Enhanced protection to also skip nostr URIs that are part of HTTP/HTTPS
URL patterns, not just markdown link URLs. This addresses timing issues
where the source markdown may contain plain URLs with nostr identifiers
before they're formatted as markdown links.

The detection checks if a nostr URI appears after 'https://' or 'http://'
and is part of a valid URL continuation to avoid false positives.
2025-11-01 00:21:14 +01:00
Gigi
08a8f5623a debug: add comprehensive logging to diagnose timing issue with link processing
Added extensive debug logs to track:
- Input markdown preview and existing link count
- Each markdown link found with context and content
- Warnings when link URLs contain nostr URIs (should be protected)
- Detailed position information for each nostr URI match
- Whether matches are correctly identified as inside/outside link URLs
- Detection of nested markdown links in result (indicates bug)

This will help diagnose the timing issue where processing sometimes
works and sometimes doesn't.
2025-11-01 00:19:43 +01:00
Gigi
e85ccdc7da fix: use parser-based approach to detect markdown link URLs
Replace regex-based markdown link detection with a character-by-character
parser that correctly handles URLs containing brackets and parentheses.
The parser tracks parenthesis depth and escaped characters to correctly
find the end of markdown link URLs, even when they contain special
characters like brackets or nested parentheses.

This should fix the issue where nostr identifiers inside markdown link
URLs were still being processed, causing nested/duplicated markdown links.
2025-11-01 00:17:08 +01:00
Gigi
d0e7f146fb debug: add extensive logging to nostrUriResolver for debugging link processing
Added debug logs prefixed with [nostrUriResolver] to track:
- When markdown processing starts
- All markdown links found and their URL ranges
- All nostr URI matches and their positions
- Whether each nostr URI is skipped or replaced
- Final processing results

This will help diagnose why nostr identifiers are still being
processed inside markdown link URLs.
2025-10-31 23:53:55 +01:00
Gigi
efdb33eb31 fix: remove unused variables in nostrUriResolver
Removed unused linkEnd variable and prefixed unused type parameter
with underscore to satisfy linter and type checker.
2025-10-31 23:52:52 +01:00
Gigi
0abbe62515 fix: prevent nostr URI replacement inside markdown link URLs
Prevents nested markdown link issues when nostr identifiers appear in URLs.
The replaceNostrUrisInMarkdown functions now skip nostr URIs that are
already inside markdown link syntax [text](url) to avoid creating
malformed nested links.
2025-10-31 23:51:40 +01:00
Gigi
ab0972dd29 docs: update CHANGELOG for v0.10.27 2025-10-31 01:59:40 +01:00
Gigi
83fbb26e03 chore: bump version to 0.10.27 v0.10.27 2025-10-31 01:58:35 +01:00
Gigi
e8ce928ec6 Merge pull request #30 from dergigi/long-form-loading-shenanigans
fix: article loading race condition and improve caching
2025-10-31 01:58:02 +01:00
Gigi
1a01e14702 fix: properly handle fetch errors in sw-dev.js
Fix scope issue where cachedResponse wasn't accessible in catch block.
Now if fetch fails, we first check if we have a cached response and
return it. If no cache exists, we let the error propagate so the
browser can handle it gracefully.
2025-10-31 01:54:39 +01:00
Gigi
aab8176987 fix: add error handling to sw-dev.js fetch requests
Add proper error handling to prevent uncaught promise rejections when
image fetches fail. If a fetch fails, try to return cached response,
or gracefully handle the error instead of letting it propagate as an
uncaught promise rejection.
2025-10-31 01:54:23 +01:00
Gigi
5a8b885d25 fix: remove bulk image preloading to prevent ERR_INSUFFICIENT_RESOURCES
Remove image preloading from BlogPostCard and profileService to prevent
trying to fetch hundreds of images simultaneously. Images are already
lazy-loaded and will be cached by Service Worker when they come into view.
Only preload images when specifically needed (e.g., when loading an article
from cache, or the logged-in user's profile image in SidebarHeader).

This fixes thousands of ERR_INSUFFICIENT_RESOURCES errors when loading
the explore page with many blog posts.
2025-10-31 01:52:53 +01:00
Gigi
c129b24352 chore: remove remaining console.log debug statements
Remove all console.log statements from Service Worker registration
and ReaderHeader image loading code, keeping only console.error and
console.warn for actual error handling.
2025-10-31 01:51:24 +01:00
Gigi
d98d750268 fix: move useEffect before early return in BlogPostCard
Move useEffect hook before the conditional early return to satisfy
React's rules of hooks. All hooks must be called before any
conditional returns to prevent 'Rendered fewer hooks than expected'
errors.
2025-10-31 01:49:08 +01:00
Gigi
8262b2bf24 chore: remove all debug console output from article cache and service worker
Remove all console.log, console.warn, and console.error statements
that were added for debugging in article cache, service worker,
and image caching code.
2025-10-31 01:47:00 +01:00
Gigi
b99f36c0c5 chore: remove unused refresh button from highlights panel header 2025-10-31 01:44:52 +01:00
Gigi
dfe37a260e chore: remove debug console.log statements from useImageCache
Remove all debug console.log statements that were added during
image caching implementation, keeping only error logs for actual
error handling.
2025-10-31 01:44:07 +01:00
Gigi
2a42f1de53 feat: add refresh button to highlights sidebar header
Add a refresh button to the highlights panel header, positioned to the
left of the eye icon. The button refreshes highlights for the current
article and shows a spinning animation while loading.
2025-10-31 01:41:36 +01:00
Gigi
cea2d0eda2 perf: avoid redundant image preload when using preview data
Skip image preload in useArticleLoader when preview data is available,
since the image should already be cached from BlogPostCard. This prevents
unnecessary network requests when navigating from explore.
2025-10-31 01:39:11 +01:00
Gigi
ef05974a72 feat: preload images in BlogPostCard for better caching
Preload article cover images when BlogPostCard is rendered to ensure
they're cached by Service Worker before navigating to the article.
This prevents re-fetching images that are already displayed in explore.
2025-10-31 01:38:49 +01:00
Gigi
5a6ac628d2 fix: add save suppression when resetting scroll position
Add 500ms save suppression when article changes to prevent
accidentally saving 0% reading position during navigation.
This works together with existing safeguards (tracking disabled,
document height check, throttling) to ensure reading progress
is only saved during actual reading.
2025-10-31 01:37:02 +01:00
Gigi
826f07544e fix: reset scroll position when switching articles
Reset scroll position to top immediately when articleIdentifier changes
to prevent showing wrong scroll position from previous article. Also
reset hasAttemptedRestoreRef when article changes to ensure proper
scroll restoration for new articles.
2025-10-31 01:35:56 +01:00
Gigi
911215c0fb feat: preload logged-in user profile image for offline access
Preload profile images when profiles are fetched and when displayed
in the sidebar to ensure they're cached by the Service Worker for
offline access.
2025-10-31 01:34:34 +01:00
Gigi
43ed41bfae chore: remove debug console.log statements
Remove all debug console.log statements that were added during
article loading and caching implementation, keeping only error
and warning logs for actual error handling.
2025-10-31 01:33:09 +01:00
Gigi
81597fbb6d fix: clear reader content immediately when naddr changes
Prevent showing stale images from previous articles by clearing
readerContent at the start of the effect when navigating to a new article.
2025-10-31 01:31:30 +01:00
Gigi
cc722c2599 fix: mark unused settings parameter as intentionally unused 2025-10-31 01:26:26 +01:00
Gigi
c20682fbe8 fix: resolve article loading race condition and populate cache from explore
- Move cache/EventStore checks before relayPool check in useArticleLoader
  to fix race condition where articles wouldn't load on direct navigation
- Add relayPool to dependency array so effect re-runs when it becomes available
- Populate localStorage cache when articles are loaded in explore view
- Extract cacheArticleEvent() helper to eliminate code duplication
- Enhance saveToCache() with settings parameter and better error handling
2025-10-31 01:24:58 +01:00
Gigi
cfa6dc4400 feat: add development Service Worker for testing image caching
With injectManifest strategy, the Service Worker needs to be built, so it's
not available in dev mode. To enable testing image caching in dev, we now:
1. Created public/sw-dev.js - a simplified SW that only handles image caching
2. Updated registration to use sw-dev.js in dev mode, sw.js in production
3. Dev SW uses simple cache-first strategy for images

This allows testing image caching in development without needing a build.
2025-10-31 01:10:20 +01:00
Gigi
851cecf18c fix: enable Service Worker registration in dev mode for testing
With devOptions.enabled: true, vite-plugin-pwa should serve the SW
in dev mode. Now we:
1. Attempt registration in both dev and prod
2. In dev mode, check if SW file exists and has correct MIME type first
3. Only register if file is actually available (not HTML fallback)
4. Handle errors gracefully with informative warnings

This allows testing image caching in dev mode when vite-plugin-pwa
is properly serving the Service Worker file.
2025-10-31 01:08:03 +01:00
Gigi
d4c67485a2 fix: skip Service Worker registration in dev mode
With injectManifest strategy, the Service Worker file is only generated
during build, so it's not available in development mode. This causes
MIME type errors when trying to register a non-existent file.

Now we:
1. Only register Service Worker in production builds
2. Skip registration gracefully in dev mode with informative log
3. Image caching will work in production but not in dev (expected)

This eliminates the 'unsupported MIME type' errors in development.
2025-10-31 01:05:01 +01:00
Gigi
381fd05c90 fix: improve Service Worker registration error handling
1. Check for existing registrations first to avoid duplicate registrations
2. In dev mode, check if SW file exists before attempting registration
3. Handle registration errors gracefully - don't crash if SW unavailable in dev
4. Use getRegistrations() instead of getRegistration() for better coverage
5. Add more detailed error logging for debugging

This prevents the 'Failed to register ServiceWorker' errors when the
SW file isn't available in development mode.
2025-10-31 00:59:39 +01:00
Gigi
60c4ef55c0 fix: enable Service Worker registration in development mode
Service Worker was only registered in production, but vite-plugin-pwa
has devOptions.enabled=true, so SW should work in dev too. Now we:
1. Register SW in both dev and prod modes
2. Use correct SW path for dev (/dev-sw.js?dev-sw) vs prod (/sw.js)
3. Add comprehensive debug logs for registration and activation
4. Log Service Worker state changes for debugging

Service Workers don't require PWA installation - they work in regular
browsers. This enables image caching in development mode.
2025-10-31 00:55:34 +01:00
Gigi
0b7891419b debug: add comprehensive logging for image caching
Add debug logs prefixed with [image-preload], [image-cache], [sw-image-cache],
and [reader-header] to track:
- When images are preloaded
- Service Worker availability and controller status
- Image fetch success/failure
- Service Worker intercepting and caching image requests
- Image loading in ReaderHeader component
- Cache hits/misses in Service Worker

This will help debug why images aren't available offline.
2025-10-31 00:52:29 +01:00
Gigi
aeedc622b1 fix: preload images when loading articles from cache
When loading articles from localStorage cache, images aren't automatically
cached by the Service Worker because they're not fetched until the <img> tag
renders. If the user goes offline before that, images won't be available.

Now we:
1. Added preloadImage() function to explicitly fetch images via Image() and fetch()
2. Preload images when loading from localStorage cache
3. Preload images when receiving first event from relays

This ensures images are cached by Service Worker before going offline,
making them available on refresh when offline.
2025-10-31 00:50:52 +01:00
Gigi
6f5b87136b fix: image caching issues
1. Fix cache name mismatch: imageCacheService now uses 'boris-images'
   to match the Service Worker cache name
2. Remove cross-origin restriction: Cache ALL images, not just
   cross-origin ones. This ensures article images from any source
   are cached by the Service Worker
3. Update comments to clarify Service Worker caching behavior

Images should now be properly cached when loaded via <img> tags.
2025-10-31 00:47:10 +01:00
Gigi
1ac0c719a2 fix: simplify cache save logic to avoid TypeScript errors
Simplify the finalization cache save - we already save on first event,
so only save in finalization if first event wasn't emitted. This
avoids TypeScript narrowing issues and duplicate cache saves.
2025-10-31 00:44:16 +01:00
Gigi
c9ce5442e0 fix: save to cache immediately when first event received
Move cache save to happen immediately when first event is received
via onEvent callback, instead of waiting for queryEvents to complete.
This ensures articles are cached even if queryEvents hangs or never
resolves.

Also deduplicate cache saves - only save again in finalization if
it's a different/newer event than the first one.
2025-10-31 00:43:11 +01:00
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
683ea27526 docs: update CHANGELOG for v0.10.26 2025-10-31 00:28:10 +01:00
Gigi
fa052483b2 chore: bump version to 0.10.26 v0.10.26 2025-10-31 00:27:14 +01:00
Gigi
0ae9e6321e Merge pull request #29 from dergigi/flight-mode-shenanigans
Fix flight mode detection and persist highlight metadata
2025-10-31 00:26:08 +01:00
Gigi
5623f2e595 chore: remove debug console.log statements
- Remove debug console.log from AddBookmarkModal.tsx (modal fetch and description extraction)
- Remove console.debug from relayManager.ts (relay closing errors)
- Keep console.warn and console.error for legitimate error handling
2025-10-31 00:24:42 +01:00
Gigi
2c94c1e3f0 fix: remove unused variables to resolve lint errors
- Remove unused relayNames variable from HighlightItem.tsx
- Remove unused failedRelays variable from highlightCreationService.ts
- All linting and type checks now pass
2025-10-31 00:18:58 +01:00
Gigi
19dc2f70f2 feat: persist highlight metadata and offline events to localStorage
- Add localStorage persistence for highlightMetadataCache Map
- Add localStorage persistence for offlineCreatedEvents Set
- Load both caches from localStorage on module initialization
- Save to localStorage whenever caches are updated
- Update metadata cache during sync operations (isSyncing changes)
- Ensures airplane icon displays correctly after page reloads
- Gracefully handles localStorage errors and corrupted data
2025-10-31 00:17:13 +01:00
Gigi
5013ccc552 perf: remove excessive debug logging for better performance
- Remove debug logs from highlight creation, publishing, and UI rendering
- Keep only essential error logging
- Improves performance by reducing console spam
- Flight mode detection still works via fallback mechanisms
2025-10-31 00:12:04 +01:00
Gigi
29eed3395f fix: prioritize isLocalOnly check to show airplane icon
- Check isLocalOnly first before checking publishedRelays length
- Show airplane icon if isLocalOnly is true, even if publishedRelays is empty
- This ensures flight mode highlights show airplane icon via offline sync fallback
- Add debug logs to track cache storage and retrieval
- Fixes issue where airplane icon doesn't show when creating highlights offline
2025-10-31 00:09:09 +01:00