diff --git a/src/components/Debug.tsx b/src/components/Debug.tsx index f167b8ba..51c164e8 100644 --- a/src/components/Debug.tsx +++ b/src/components/Debug.tsx @@ -781,9 +781,16 @@ const Debug: React.FC = ({ } }) - // Load deduplicated results via controller + // Load deduplicated results via controller (includes articles and external URLs) const unsubProgress = readingProgressController.onProgress((progressMap) => { setDeduplicatedProgressMap(new Map(progressMap)) + + // Regression guard: ensure keys include both naddr and raw URL forms when present + try { + const keys = Array.from(progressMap.keys()) + const sample = keys.slice(0, 5).join(', ') + DebugBus.info('debug', `Progress keys sample: ${sample}`) + } catch {} }) // Run both in parallel diff --git a/src/services/readingDataProcessor.ts b/src/services/readingDataProcessor.ts index 5c512fa3..b2c26de3 100644 --- a/src/services/readingDataProcessor.ts +++ b/src/services/readingDataProcessor.ts @@ -75,10 +75,17 @@ export function processReadingProgress( continue } } else if (dTag.startsWith('url:')) { - // It's a URL with base64url encoding - const encoded = dTag.replace('url:', '') + // It's a URL. We support both raw URLs and base64url-encoded URLs. + const value = dTag.slice(4) + const looksBase64Url = /^[A-Za-z0-9_-]+$/.test(value) && (value.includes('-') || value.includes('_')) try { - itemUrl = atob(encoded.replace(/-/g, '+').replace(/_/g, '/')) + if (looksBase64Url) { + // Decode base64url to raw URL + itemUrl = atob(value.replace(/-/g, '+').replace(/_/g, '/')) + } else { + // Treat as raw URL (already decoded) + itemUrl = value + } itemId = itemUrl itemType = 'external' } catch (e) { diff --git a/src/services/readingPositionService.ts b/src/services/readingPositionService.ts index 56d5f0cc..9602237a 100644 --- a/src/services/readingPositionService.ts +++ b/src/services/readingPositionService.ts @@ -98,11 +98,8 @@ export function generateArticleIdentifier(naddrOrUrl: string): string { if (naddrOrUrl.startsWith('nostr:')) { return naddrOrUrl.replace('nostr:', '') } - // For URLs, use base64url encoding (URL-safe) - return btoa(naddrOrUrl) - .replace(/\+/g, '-') - .replace(/\//g, '_') - .replace(/=+$/, '') + // For URLs, return the raw URL. Downstream tag generation will encode as needed. + return naddrOrUrl } /** diff --git a/src/services/readingProgressController.ts b/src/services/readingProgressController.ts index f4949355..3d0af404 100644 --- a/src/services/readingProgressController.ts +++ b/src/services/readingProgressController.ts @@ -276,10 +276,10 @@ class ReadingProgressController { // Process new events processReadingProgress(events, readsMap) - // Convert back to progress map (naddr -> progress) + // Convert back to progress map (id -> progress). Include both articles and external URLs. const newProgressMap = new Map() for (const [id, item] of readsMap.entries()) { - if (item.readingProgress !== undefined && item.type === 'article') { + if (item.readingProgress !== undefined) { newProgressMap.set(id, item.readingProgress) } }