- {/* Theme Toggle in Menu */}
-
- Theme
-
-
-
{/* Login Area in Menu */}
Account
@@ -83,35 +48,39 @@ export function BlogHeader() {
{/* Navigation for logged in users */}
{user && (
- <>
-
-
-
-
-
-
- >
+
+
+
+
+
+
)}
+
+ {/* 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 && (
+
+ )}
+
+ {/* 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 && (
-
- )}
-
- {/* 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.
+
+
+
+
+
+
+ )}
+