mirror of
https://github.com/mroxso/zelo-news.git
synced 2026-04-22 20:57:55 +02:00
Rename BlogPostPage to ArticlePage and refactor related components
This commit is contained in:
@@ -136,7 +136,7 @@ src/
|
||||
│ └── useZaps.ts # Lightning payments
|
||||
├── pages/
|
||||
│ ├── BlogHomePage.tsx # Homepage with article feed
|
||||
│ ├── BlogPostPage.tsx # Individual article view
|
||||
│ ├── ArticlePage.tsx # Individual article view
|
||||
│ ├── CreatePostPage.tsx # Article editor
|
||||
│ └── EditPostPage.tsx # Edit existing articles
|
||||
├── contexts/ # React context providers
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useParams, Link } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { useBlogPost } from '@/hooks/useBlogPost';
|
||||
import { useAuthor } from '@/hooks/useAuthor';
|
||||
import type { NostrEvent } from '@nostrify/nostrify';
|
||||
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
||||
import { useAuthor } from '@/hooks/useAuthor';
|
||||
import { useReactions, useReact } from '@/hooks/useReactions';
|
||||
import { MarkdownContent } from '@/components/MarkdownContent';
|
||||
import { CommentsSection } from '@/components/comments/CommentsSection';
|
||||
@@ -11,7 +11,6 @@ import { BookmarkButton } from '@/components/BookmarkButton';
|
||||
import { ReadingTime } from '@/components/ReadingTime';
|
||||
import { ArticleProgressBar } from '@/components/ArticleProgressBar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
@@ -20,7 +19,6 @@ import { genUserName } from '@/lib/genUserName';
|
||||
import { calculateReadingTime } from '@/lib/calculateReadingTime';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { useState } from 'react';
|
||||
import NotFound from '@/pages/NotFound';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -31,72 +29,31 @@ import {
|
||||
} from '@/components/ui/dialog';
|
||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
|
||||
export default function BlogPostPage() {
|
||||
const { nip19: naddr } = useParams<{ nip19: string }>();
|
||||
interface ArticleViewProps {
|
||||
post: NostrEvent;
|
||||
}
|
||||
|
||||
export function ArticleView({ post }: ArticleViewProps) {
|
||||
const { user } = useCurrentUser();
|
||||
const { toast } = useToast();
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [jsonCopied, setJsonCopied] = useState(false);
|
||||
|
||||
// Decode naddr
|
||||
let pubkey = '';
|
||||
let identifier = '';
|
||||
let kind = 0;
|
||||
let isValidNaddr = false;
|
||||
|
||||
try {
|
||||
if (naddr?.startsWith('naddr1')) {
|
||||
const decoded = nip19.decode(naddr);
|
||||
if (decoded.type === 'naddr') {
|
||||
pubkey = decoded.data.pubkey;
|
||||
identifier = decoded.data.identifier;
|
||||
kind = decoded.data.kind;
|
||||
isValidNaddr = true;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to decode naddr:', error);
|
||||
}
|
||||
|
||||
const { data: post, isLoading } = useBlogPost(pubkey, identifier);
|
||||
const author = useAuthor(pubkey);
|
||||
const { data: reactions } = useReactions(post?.id || '', pubkey);
|
||||
const author = useAuthor(post.pubkey);
|
||||
const { data: reactions } = useReactions(post.id, post.pubkey);
|
||||
const { mutate: react } = useReact();
|
||||
|
||||
const metadata = author.data?.metadata;
|
||||
const displayName = metadata?.display_name || metadata?.name || genUserName(pubkey);
|
||||
const displayName = metadata?.display_name || metadata?.name || genUserName(post.pubkey);
|
||||
|
||||
// Check if the current user is the author of this post
|
||||
const isPostAuthor = user?.pubkey === post?.pubkey;
|
||||
const isPostAuthor = user?.pubkey === post.pubkey;
|
||||
const hasReacted = reactions?.likes.some(like => like.pubkey === user?.pubkey);
|
||||
|
||||
if (!isValidNaddr || !naddr || kind !== 30023) {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<div className="container max-w-4xl py-8 px-4 sm:px-6 lg:px-8">
|
||||
<Skeleton className="h-8 w-24 mb-6" />
|
||||
<div className="space-y-4">
|
||||
<Skeleton className="h-12 w-3/4" />
|
||||
<Skeleton className="h-6 w-1/2" />
|
||||
<Skeleton className="h-64 w-full mt-8" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!post) {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
const title = post.tags.find(([name]) => name === 'title')?.[1] || 'Untitled';
|
||||
const summary = post.tags.find(([name]) => name === 'summary')?.[1];
|
||||
const image = post.tags.find(([name]) => name === 'image')?.[1];
|
||||
const publishedAt = post.tags.find(([name]) => name === 'published_at')?.[1];
|
||||
const identifier = post.tags.find(([name]) => name === 'd')?.[1] || '';
|
||||
const hashtags = post.tags
|
||||
.filter(([name]) => name === 't')
|
||||
.map(([, value]) => value);
|
||||
@@ -105,7 +62,6 @@ export default function BlogPostPage() {
|
||||
? new Date(parseInt(publishedAt) * 1000)
|
||||
: new Date(post.created_at * 1000);
|
||||
|
||||
// Calculate reading time
|
||||
const readingTime = calculateReadingTime(post.content);
|
||||
|
||||
const handleReact = () => {
|
||||
@@ -134,7 +90,6 @@ export default function BlogPostPage() {
|
||||
};
|
||||
|
||||
const handleCopyJson = async () => {
|
||||
if (!post) return;
|
||||
try {
|
||||
const jsonString = JSON.stringify(post, null, 2);
|
||||
await navigator.clipboard.writeText(jsonString);
|
||||
@@ -155,11 +110,9 @@ export default function BlogPostPage() {
|
||||
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
{/* Sticky progress bar */}
|
||||
<ArticleProgressBar />
|
||||
|
||||
<article className="container max-w-4xl py-8 px-4 sm:px-6 lg:px-8">
|
||||
{/* Back button */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@@ -170,7 +123,6 @@ export default function BlogPostPage() {
|
||||
Back
|
||||
</Button>
|
||||
|
||||
{/* Post header */}
|
||||
<header className="space-y-6 mb-8">
|
||||
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-bold leading-tight">
|
||||
{title}
|
||||
@@ -182,12 +134,10 @@ export default function BlogPostPage() {
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Reading time */}
|
||||
<ReadingTime minutes={readingTime} />
|
||||
|
||||
{/* Author info and metadata */}
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||||
<Link to={`/${nip19.npubEncode(pubkey)}`} className="flex items-center gap-3 hover:opacity-80 transition-opacity">
|
||||
<Link to={`/${nip19.npubEncode(post.pubkey)}`} className="flex items-center gap-3 hover:opacity-80 transition-opacity">
|
||||
<Avatar className="h-10 w-10 sm:h-12 sm:w-12">
|
||||
<AvatarImage src={metadata?.picture} alt={displayName} />
|
||||
<AvatarFallback>{displayName[0]?.toUpperCase()}</AvatarFallback>
|
||||
@@ -232,7 +182,6 @@ export default function BlogPostPage() {
|
||||
)}
|
||||
</header>
|
||||
|
||||
{/* Cover image */}
|
||||
{image && (
|
||||
<div className="mb-8 rounded-lg overflow-hidden">
|
||||
<img
|
||||
@@ -243,14 +192,12 @@ export default function BlogPostPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Post content */}
|
||||
<div className="mb-12">
|
||||
<MarkdownContent content={post.content} />
|
||||
</div>
|
||||
|
||||
<Separator className="my-8" />
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex flex-wrap items-center gap-4 mb-12">
|
||||
<Button
|
||||
variant={hasReacted ? "default" : "outline"}
|
||||
@@ -335,10 +282,7 @@ export default function BlogPostPage() {
|
||||
|
||||
<Separator className="my-8" />
|
||||
|
||||
{/* Comments section */}
|
||||
<CommentsSection
|
||||
root={post}
|
||||
/>
|
||||
<CommentsSection root={post} />
|
||||
</article>
|
||||
</div>
|
||||
);
|
||||
@@ -1,54 +1,13 @@
|
||||
import { useParams, Link } from 'react-router-dom';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useBlogPostByDTag } from '@/hooks/useBlogPostByDTag';
|
||||
import { useAuthor } from '@/hooks/useAuthor';
|
||||
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
||||
import { useReactions, useReact } from '@/hooks/useReactions';
|
||||
import { MarkdownContent } from '@/components/MarkdownContent';
|
||||
import { CommentsSection } from '@/components/comments/CommentsSection';
|
||||
import { ZapButton } from '@/components/ZapButton';
|
||||
import { BookmarkButton } from '@/components/BookmarkButton';
|
||||
import { ReadingTime } from '@/components/ReadingTime';
|
||||
import { ArticleProgressBar } from '@/components/ArticleProgressBar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { ArticleView } from '@/components/ArticleView';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { Calendar, Heart, Edit, ArrowLeft, Share2, Check, Code } from 'lucide-react';
|
||||
import { genUserName } from '@/lib/genUserName';
|
||||
import { calculateReadingTime } from '@/lib/calculateReadingTime';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { useState } from 'react';
|
||||
import NotFound from '@/pages/NotFound';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/components/ui/dialog';
|
||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
|
||||
export default function ArticleByDTagPage() {
|
||||
const { dtag } = useParams<{ dtag: string }>();
|
||||
const { user } = useCurrentUser();
|
||||
const { toast } = useToast();
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [jsonCopied, setJsonCopied] = useState(false);
|
||||
|
||||
const { data: post, isLoading } = useBlogPostByDTag(dtag || '');
|
||||
const author = useAuthor(post?.pubkey || '');
|
||||
const { data: reactions } = useReactions(post?.id || '', post?.pubkey || '');
|
||||
const { mutate: react } = useReact();
|
||||
|
||||
const metadata = author.data?.metadata;
|
||||
const displayName = metadata?.display_name || metadata?.name || genUserName(post?.pubkey || '');
|
||||
|
||||
// Check if the current user is the author of this post
|
||||
const isPostAuthor = user?.pubkey === post?.pubkey;
|
||||
const hasReacted = reactions?.likes.some(like => like.pubkey === user?.pubkey);
|
||||
|
||||
if (!dtag) {
|
||||
return <NotFound />;
|
||||
@@ -73,254 +32,5 @@ export default function ArticleByDTagPage() {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
const title = post.tags.find(([name]) => name === 'title')?.[1] || 'Untitled';
|
||||
const summary = post.tags.find(([name]) => name === 'summary')?.[1];
|
||||
const image = post.tags.find(([name]) => name === 'image')?.[1];
|
||||
const publishedAt = post.tags.find(([name]) => name === 'published_at')?.[1];
|
||||
const identifier = post.tags.find(([name]) => name === 'd')?.[1] || '';
|
||||
const hashtags = post.tags
|
||||
.filter(([name]) => name === 't')
|
||||
.map(([, value]) => value);
|
||||
|
||||
const date = publishedAt
|
||||
? new Date(parseInt(publishedAt) * 1000)
|
||||
: new Date(post.created_at * 1000);
|
||||
|
||||
// Calculate reading time
|
||||
const readingTime = calculateReadingTime(post.content);
|
||||
|
||||
const handleReact = () => {
|
||||
if (!user) return;
|
||||
if (hasReacted) return;
|
||||
react({ eventId: post.id, eventAuthor: post.pubkey });
|
||||
};
|
||||
|
||||
const handleShare = async () => {
|
||||
try {
|
||||
const articleUrl = window.location.href;
|
||||
await navigator.clipboard.writeText(articleUrl);
|
||||
setCopied(true);
|
||||
toast({
|
||||
title: "Link copied!",
|
||||
description: "Article link copied to clipboard",
|
||||
});
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
} catch {
|
||||
toast({
|
||||
title: "Failed to copy",
|
||||
description: "Could not copy link to clipboard",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleCopyJson = async () => {
|
||||
if (!post) return;
|
||||
try {
|
||||
const jsonString = JSON.stringify(post, null, 2);
|
||||
await navigator.clipboard.writeText(jsonString);
|
||||
setJsonCopied(true);
|
||||
toast({
|
||||
title: "JSON copied!",
|
||||
description: "Raw event data copied to clipboard",
|
||||
});
|
||||
setTimeout(() => setJsonCopied(false), 2000);
|
||||
} catch {
|
||||
toast({
|
||||
title: "Failed to copy",
|
||||
description: "Could not copy JSON to clipboard",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
{/* Sticky progress bar */}
|
||||
<ArticleProgressBar />
|
||||
|
||||
<article className="container max-w-4xl py-8 px-4 sm:px-6 lg:px-8">
|
||||
{/* Back button */}
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => window.history.back()}
|
||||
className="mb-6"
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
Back
|
||||
</Button>
|
||||
|
||||
{/* Post header */}
|
||||
<header className="space-y-6 mb-8">
|
||||
<h1 className="text-3xl sm:text-4xl lg:text-5xl font-bold leading-tight">
|
||||
{title}
|
||||
</h1>
|
||||
|
||||
{summary && (
|
||||
<p className="text-lg sm:text-xl text-muted-foreground">
|
||||
{summary}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{/* Reading time */}
|
||||
<ReadingTime minutes={readingTime} />
|
||||
|
||||
{/* Author info and metadata */}
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||||
<Link to={`/${nip19.npubEncode(post.pubkey)}`} className="flex items-center gap-3 hover:opacity-80 transition-opacity">
|
||||
<Avatar className="h-10 w-10 sm:h-12 sm:w-12">
|
||||
<AvatarImage src={metadata?.picture} alt={displayName} />
|
||||
<AvatarFallback>{displayName[0]?.toUpperCase()}</AvatarFallback>
|
||||
</Avatar>
|
||||
<div>
|
||||
<div className="font-semibold">{displayName}</div>
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Calendar className="h-3 w-3" />
|
||||
<time dateTime={date.toISOString()}>
|
||||
{date.toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
})}
|
||||
</time>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
{isPostAuthor && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
asChild
|
||||
>
|
||||
<Link to={`/edit/${identifier}`}>
|
||||
<Edit className="h-4 w-4 mr-2" />
|
||||
Edit
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{hashtags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{hashtags.map((tag) => (
|
||||
<Badge key={tag} variant="secondary">
|
||||
#{tag}
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
||||
{/* Cover image */}
|
||||
{image && (
|
||||
<div className="mb-8 rounded-lg overflow-hidden">
|
||||
<img
|
||||
src={image}
|
||||
alt={title}
|
||||
className="w-full h-auto max-h-[500px] object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Post content */}
|
||||
<div className="mb-12">
|
||||
<MarkdownContent content={post.content} />
|
||||
</div>
|
||||
|
||||
<Separator className="my-8" />
|
||||
|
||||
{/* Actions */}
|
||||
<div className="flex flex-wrap items-center gap-4 mb-12">
|
||||
<Button
|
||||
variant={hasReacted ? "default" : "outline"}
|
||||
onClick={handleReact}
|
||||
disabled={!user || hasReacted}
|
||||
className="gap-2"
|
||||
>
|
||||
<Heart className={`h-4 w-4 ${hasReacted ? 'fill-current' : ''}`} />
|
||||
<span className="text-xs">
|
||||
{reactions?.likeCount || 0}
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
<ZapButton
|
||||
target={post}
|
||||
showCount={true}
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleShare}
|
||||
className="gap-2"
|
||||
>
|
||||
{copied ? (
|
||||
<Check className="h-4 w-4" />
|
||||
) : (
|
||||
<Share2 className="h-4 w-4" />
|
||||
)}
|
||||
<span className="text-xs">Share</span>
|
||||
</Button>
|
||||
|
||||
<BookmarkButton
|
||||
articleCoordinate={`${post.kind}:${post.pubkey}:${identifier}`}
|
||||
variant="outline"
|
||||
size="default"
|
||||
showText={true}
|
||||
/>
|
||||
|
||||
<Dialog>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="gap-2"
|
||||
>
|
||||
<Code className="h-4 w-4" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="max-w-3xl max-h-[80vh]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Raw Event Data</DialogTitle>
|
||||
<DialogDescription>
|
||||
NIP-23 blog post event (kind {post.kind})
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<ScrollArea className="h-[60vh] w-full rounded-md border p-4">
|
||||
<pre className="text-xs font-mono">
|
||||
{JSON.stringify(post, null, 2)}
|
||||
</pre>
|
||||
</ScrollArea>
|
||||
<div className="flex justify-end">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleCopyJson}
|
||||
className="gap-2"
|
||||
>
|
||||
{jsonCopied ? (
|
||||
<>
|
||||
<Check className="h-4 w-4" />
|
||||
Copied!
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Code className="h-4 w-4" />
|
||||
Copy JSON
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</div>
|
||||
|
||||
<Separator className="my-8" />
|
||||
|
||||
{/* Comments section */}
|
||||
<CommentsSection
|
||||
root={post}
|
||||
/>
|
||||
</article>
|
||||
</div>
|
||||
);
|
||||
return <ArticleView post={post} />;
|
||||
}
|
||||
|
||||
56
src/pages/ArticlePage.tsx
Normal file
56
src/pages/ArticlePage.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { useBlogPost } from '@/hooks/useBlogPost';
|
||||
import { ArticleView } from '@/components/ArticleView';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import NotFound from '@/pages/NotFound';
|
||||
|
||||
export default function ArticlePage() {
|
||||
const { nip19: naddr } = useParams<{ nip19: string }>();
|
||||
|
||||
let pubkey = '';
|
||||
let identifier = '';
|
||||
let kind = 0;
|
||||
let isValidNaddr = false;
|
||||
|
||||
try {
|
||||
if (naddr?.startsWith('naddr1')) {
|
||||
const decoded = nip19.decode(naddr);
|
||||
if (decoded.type === 'naddr') {
|
||||
pubkey = decoded.data.pubkey;
|
||||
identifier = decoded.data.identifier;
|
||||
kind = decoded.data.kind;
|
||||
isValidNaddr = true;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to decode naddr:', error);
|
||||
}
|
||||
|
||||
const { data: post, isLoading } = useBlogPost(pubkey, identifier);
|
||||
|
||||
if (!isValidNaddr || !naddr || kind !== 30023) {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="min-h-screen">
|
||||
<div className="container max-w-4xl py-8 px-4 sm:px-6 lg:px-8">
|
||||
<Skeleton className="h-8 w-24 mb-6" />
|
||||
<div className="space-y-4">
|
||||
<Skeleton className="h-12 w-3/4" />
|
||||
<Skeleton className="h-6 w-1/2" />
|
||||
<Skeleton className="h-64 w-full mt-8" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!post) {
|
||||
return <NotFound />;
|
||||
}
|
||||
|
||||
return <ArticleView post={post} />;
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import ProfilePage from './ProfilePage';
|
||||
import BlogPostPage from './BlogPostPage';
|
||||
import ArticlePage from './ArticlePage';
|
||||
import { NotePage } from './NotePage';
|
||||
import { EventPage } from './EventPage';
|
||||
import NotFound from './NotFound';
|
||||
@@ -46,8 +46,8 @@ export function NIP19Page() {
|
||||
}
|
||||
|
||||
case 'naddr':
|
||||
// Render addressable event (blog post) - BlogPostPage will handle validation
|
||||
return <BlogPostPage />;
|
||||
// Render addressable event (blog post) - ArticlePage will handle validation
|
||||
return <ArticlePage />;
|
||||
|
||||
default:
|
||||
return <NotFound />;
|
||||
|
||||
Reference in New Issue
Block a user