diff --git a/src/components/BookmarkItem.tsx b/src/components/BookmarkItem.tsx index 2d75f737..5fe64a41 100644 --- a/src/components/BookmarkItem.tsx +++ b/src/components/BookmarkItem.tsx @@ -19,9 +19,10 @@ interface BookmarkItemProps { index: number onSelectUrl?: (url: string, bookmark?: { id: string; kind: number; tags: string[][]; pubkey: string }) => void viewMode?: ViewMode + readingProgress?: number } -export const BookmarkItem: React.FC = ({ bookmark, index, onSelectUrl, viewMode = 'cards' }) => { +export const BookmarkItem: React.FC = ({ bookmark, index, onSelectUrl, viewMode = 'cards', readingProgress }) => { const [ogImage, setOgImage] = useState(null) const short = (v: string) => `${v.slice(0, 8)}...${v.slice(-8)}` @@ -139,7 +140,8 @@ export const BookmarkItem: React.FC = ({ bookmark, index, onS handleReadNow, articleImage, articleSummary, - contentTypeIcon: getContentTypeIcon() + contentTypeIcon: getContentTypeIcon(), + readingProgress } if (viewMode === 'compact') { diff --git a/src/components/BookmarkViews/CardView.tsx b/src/components/BookmarkViews/CardView.tsx index f8dd673f..09695a72 100644 --- a/src/components/BookmarkViews/CardView.tsx +++ b/src/components/BookmarkViews/CardView.tsx @@ -24,6 +24,7 @@ interface CardViewProps { articleImage?: string articleSummary?: string contentTypeIcon: IconDefinition + readingProgress?: number } export const CardView: React.FC = ({ @@ -38,7 +39,8 @@ export const CardView: React.FC = ({ handleReadNow, articleImage, articleSummary, - contentTypeIcon + contentTypeIcon, + readingProgress }) => { const firstUrl = hasUrls ? extractedUrls[0] : null const firstUrlClassificationType = firstUrl ? classifyUrl(firstUrl)?.type : null @@ -52,6 +54,14 @@ export const CardView: React.FC = ({ const shouldTruncate = !expanded && contentLength > 210 const isArticle = bookmark.kind === 30023 + // Calculate progress color (matching BlogPostCard logic) + let progressColor = '#6366f1' // Default blue (reading) + if (readingProgress && readingProgress >= 0.95) { + progressColor = '#10b981' // Green (completed) + } else if (readingProgress && readingProgress > 0 && readingProgress <= 0.10) { + progressColor = 'var(--color-text)' // Neutral text color (started) + } + // Determine which image to use (article image, instant preview, or OG image) const previewImage = articleImage || instantPreview || ogImage const cachedImage = useImageCache(previewImage || undefined) @@ -163,6 +173,28 @@ export const CardView: React.FC = ({ )} + {/* Reading progress indicator for articles */} + {isArticle && readingProgress !== undefined && readingProgress > 0 && ( +
+
+
+ )} +
void articleSummary?: string contentTypeIcon: IconDefinition + readingProgress?: number } export const CompactView: React.FC = ({ @@ -22,12 +23,21 @@ export const CompactView: React.FC = ({ extractedUrls, onSelectUrl, articleSummary, - contentTypeIcon + contentTypeIcon, + readingProgress }) => { const isArticle = bookmark.kind === 30023 const isWebBookmark = bookmark.kind === 39701 const isClickable = hasUrls || isArticle || isWebBookmark + // Calculate progress color (matching BlogPostCard logic) + let progressColor = '#6366f1' // Default blue (reading) + if (readingProgress && readingProgress >= 0.95) { + progressColor = '#10b981' // Green (completed) + } else if (readingProgress && readingProgress > 0 && readingProgress <= 0.10) { + progressColor = 'var(--color-text)' // Neutral text color (started) + } + const handleCompactClick = () => { if (!onSelectUrl) return @@ -62,6 +72,28 @@ export const CompactView: React.FC = ({ {formatDateCompact(bookmark.created_at)} {/* CTA removed */}
+ + {/* Reading progress indicator for articles */} + {isArticle && readingProgress !== undefined && readingProgress > 0 && ( +
+
+
+ )}
) } diff --git a/src/components/Me.tsx b/src/components/Me.tsx index 90449b78..86fe3726 100644 --- a/src/components/Me.tsx +++ b/src/components/Me.tsx @@ -471,6 +471,25 @@ const Me: React.FC = ({ } } + // Helper to get reading progress for a bookmark + const getBookmarkReadingProgress = (bookmark: IndividualBookmark): number | undefined => { + if (bookmark.kind === 30023) { + const dTag = bookmark.tags.find(t => t[0] === 'd')?.[1] + if (!dTag) return undefined + try { + const naddr = nip19.naddrEncode({ + kind: 30023, + pubkey: bookmark.pubkey, + identifier: dTag + }) + return readingProgressMap.get(naddr) + } catch (err) { + return undefined + } + } + return undefined + } + // Merge and flatten all individual bookmarks const allIndividualBookmarks = bookmarks.flatMap(b => b.individualBookmarks || []) .filter(hasContent) @@ -567,6 +586,7 @@ const Me: React.FC = ({ index={index} viewMode="cards" onSelectUrl={handleSelectUrl} + readingProgress={getBookmarkReadingProgress(individualBookmark)} /> ))}