From f173a84bef71a45d4c100c5f1fdcdb617dde04de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 6 Oct 2025 18:11:03 +0000 Subject: [PATCH] Fix navigation, add highlights tab to profile, enable markdown highlighting, extract HighlightCard component Co-authored-by: mroxso <24775431+mroxso@users.noreply.github.com> --- src/components/BlogHeader.tsx | 101 ++++++--------- src/components/MarkdownContent.tsx | 2 +- src/components/highlights/HighlightCard.tsx | 130 ++++++++++++++++++++ src/pages/HighlightsPage.tsx | 117 +----------------- src/pages/ProfilePage.tsx | 71 +++++++++-- 5 files changed, 232 insertions(+), 189 deletions(-) create mode 100644 src/components/highlights/HighlightCard.tsx diff --git a/src/components/BlogHeader.tsx b/src/components/BlogHeader.tsx index 033a73f..35d56e3 100644 --- a/src/components/BlogHeader.tsx +++ b/src/components/BlogHeader.tsx @@ -22,45 +22,16 @@ export function BlogHeader() { - {/* Desktop Navigation */} - {user && ( - - )} {/* Desktop Actions */} -
+
- {/* Mobile Menu */} -
+ {/* Burger Menu (shown on tablets and mobile) */} +
- - - -
- +
+ + + + +
)} + + {/* Theme Toggle in Menu */} +
+ Theme + +
diff --git a/src/components/MarkdownContent.tsx b/src/components/MarkdownContent.tsx index 77c9e28..88d4388 100644 --- a/src/components/MarkdownContent.tsx +++ b/src/components/MarkdownContent.tsx @@ -15,7 +15,7 @@ interface MarkdownContentProps { */ export function MarkdownContent({ content, className }: MarkdownContentProps) { return ( -
+
+ +
+
+ + + {displayName[0]?.toUpperCase()} + +
+ + {displayName} + + +
+
+ {isQuote && ( + + + Quote + + )} +
+
+ + {/* Highlighted text */} +
+

“{highlight.content}”

+
+ + {/* Comment if it's a quote highlight */} + {comment && ( +
+

{comment}

+
+ )} + + {/* Link to source */} + {articleLink && ( +
+ {source?.type === 'address' ? ( + + + View article + + ) : ( + + + View source + + )} +
+ )} +
+ + ); +} diff --git a/src/pages/HighlightsPage.tsx b/src/pages/HighlightsPage.tsx index bc20fee..7a1c7a1 100644 --- a/src/pages/HighlightsPage.tsx +++ b/src/pages/HighlightsPage.tsx @@ -3,121 +3,8 @@ import { useUserHighlights } from '@/hooks/useUserHighlights'; import { Card, CardContent, CardHeader } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; import { LoginArea } from '@/components/auth/LoginArea'; -import { Highlighter, ExternalLink, MessageSquare } from 'lucide-react'; -import { Link } from 'react-router-dom'; -import { nip19 } from 'nostr-tools'; -import { getHighlightSource, getHighlightComment, isQuoteHighlight } from '@/lib/validators'; -import { useAuthor } from '@/hooks/useAuthor'; -import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; -import { Badge } from '@/components/ui/badge'; -import { genUserName } from '@/lib/genUserName'; - -function HighlightCard({ highlight }: { highlight: { id: string; pubkey: string; content: string; created_at: number; tags: string[][] } }) { - const source = getHighlightSource(highlight as never); - const comment = getHighlightComment(highlight as never); - const isQuote = isQuoteHighlight(highlight as never); - const { data: author } = useAuthor(highlight.pubkey); - const metadata = author?.metadata; - - const displayName = metadata?.name || metadata?.display_name || genUserName(highlight.pubkey); - const avatarUrl = metadata?.picture; - - // Parse source to get article link - let articleLink: string | null = null; - if (source?.type === 'address') { - // Parse a-tag: "30023:pubkey:d-tag" - const parts = source.value.split(':'); - if (parts.length === 3) { - const [kind, pubkey, identifier] = parts; - const naddr = nip19.naddrEncode({ - kind: parseInt(kind), - pubkey: pubkey, - identifier: identifier, - }); - articleLink = `/${naddr}`; - } - } else if (source?.type === 'url') { - articleLink = source.value; - } - - const date = new Date(highlight.created_at * 1000); - - return ( - - -
-
- - - {displayName[0]?.toUpperCase()} - -
- - {displayName} - - -
-
- {isQuote && ( - - - Quote - - )} -
-
- - {/* Highlighted text */} -
-

“{highlight.content}”

-
- - {/* Comment if it's a quote highlight */} - {comment && ( -
-

{comment}

-
- )} - - {/* Link to source */} - {articleLink && ( -
- {source?.type === 'address' ? ( - - - View article - - ) : ( - - - View source - - )} -
- )} -
-
- ); -} +import { Highlighter } from 'lucide-react'; +import { HighlightCard } from '@/components/highlights/HighlightCard'; function HighlightsSkeleton() { return ( diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx index cd69d59..1b43299 100644 --- a/src/pages/ProfilePage.tsx +++ b/src/pages/ProfilePage.tsx @@ -3,16 +3,18 @@ import { nip19 } from 'nostr-tools'; import { useAuthor } from '@/hooks/useAuthor'; import { useAuthorBlogPosts } from '@/hooks/useAuthorBlogPosts'; import { useUserBookmarkedArticles } from '@/hooks/useUserBookmarkedArticles'; +import { useUserHighlights } from '@/hooks/useUserHighlights'; import { Card, CardContent, CardHeader } from '@/components/ui/card'; import { Skeleton } from '@/components/ui/skeleton'; import { Badge } from '@/components/ui/badge'; import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; import { Button } from '@/components/ui/button'; import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; -import { Link2, Mail, Copy, Check, Bookmark } from 'lucide-react'; +import { Link2, Mail, Copy, Check, Bookmark, Highlighter } from 'lucide-react'; import { genUserName } from '@/lib/genUserName'; import { RelaySelector } from '@/components/RelaySelector'; import { ArticlePreview } from '@/components/ArticlePreview'; +import { HighlightCard } from '@/components/highlights/HighlightCard'; import { useToast } from '@/hooks/useToast'; import NotFound from '@/pages/NotFound'; import { useState } from 'react'; @@ -47,6 +49,7 @@ export default function ProfilePage() { const author = useAuthor(pubkey); const { data: posts, isLoading: postsLoading } = useAuthorBlogPosts(pubkey); const { data: bookmarkedArticles, isLoading: bookmarksLoading } = useUserBookmarkedArticles(pubkey); + const { data: highlights, isLoading: highlightsLoading } = useUserHighlights(pubkey); const metadata = author.data?.metadata; const displayName = metadata?.display_name || metadata?.name || genUserName(pubkey); @@ -216,24 +219,33 @@ export default function ProfilePage() { {/* Content Tabs */}
- - - Published Articles + + + Published {posts && posts.length > 0 && ( {posts.length} )} - - - Bookmarks + + + Bookmarks {bookmarkedArticles && bookmarkedArticles.length > 0 && ( {bookmarkedArticles.length} )} + + + Highlights + {highlights && highlights.length > 0 && ( + + {highlights.length} + + )} + {/* Published Articles Tab */} @@ -307,6 +319,51 @@ export default function ProfilePage() { )} + + {/* Highlights Tab */} + + {highlightsLoading ? ( +
+ {[1, 2, 3].map((i) => ( + + +
+ +
+ + +
+
+
+ + + +
+ ))} +
+ ) : highlights && highlights.length > 0 ? ( +
+ {highlights.map((highlight) => ( + + ))} +
+ ) : ( + + +
+ +
+

No Highlights

+

+ This user hasn't created any highlights yet. +

+
+ +
+
+
+ )} +