From bdd42b9d26995393dc161f0a8e746c19bde5c62e Mon Sep 17 00:00:00 2001 From: gbanyan Date: Sat, 14 Feb 2026 09:57:00 +0800 Subject: [PATCH] feat: display Mastodon post media inline (images, video, gif) Co-authored-by: Cursor --- components/hero-section.tsx | 2 +- components/mastodon-feed.tsx | 79 ++++++++++++++++++++++++++++++++++-- components/nav-menu.tsx | 26 ++++++------ components/search-modal.tsx | 6 +-- components/site-header.tsx | 38 +++++++++-------- lib/mastodon.ts | 9 ++-- 6 files changed, 120 insertions(+), 40 deletions(-) diff --git a/components/hero-section.tsx b/components/hero-section.tsx index 923d37f..d744fe8 100644 --- a/components/hero-section.tsx +++ b/components/hero-section.tsx @@ -89,7 +89,7 @@ export function HeroSection({ title, tagline }: HeroSectionProps) { }, [reducedMotion]); return ( -
+
{/* Matrix rain - full area, fades out */} {!reducedMotion && (
- {/* Media indicator */} + {/* Media attachments - render images/videos from remote URLs */} {hasMedia && ( -
- πŸ“Ž εŒ…ε« {displayStatus.media_attachments.length} 個εͺ’ι«” +
+ {displayStatus.media_attachments.map((att) => { + const src = att.preview_url ?? att.url; + if (!src) return null; + + if (att.type === 'image') { + return ( + {att.description + ); + } + if (att.type === 'gifv' && att.url) { + return ( +
e.stopPropagation()} + > +
+ ); + } + if (att.type === 'video' && att.url) { + return ( +
e.stopPropagation()} + > +
+ ); + } + if (att.type === 'audio' && att.preview_url) { + return ( +
+ {att.description +
+ ); + } + return null; + })}
)} diff --git a/components/nav-menu.tsx b/components/nav-menu.tsx index 29d2fc8..625ca94 100644 --- a/components/nav-menu.tsx +++ b/components/nav-menu.tsx @@ -131,8 +131,8 @@ export function NavMenu({ items }: NavMenuProps) { className="motion-link inline-flex items-center gap-2 rounded-xl px-3 py-2 text-sm text-slate-600 hover:bg-slate-100 hover:text-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 dark:text-slate-200 dark:hover:bg-slate-800" onClick={close} > - - {item.label} + + {item.label} ) : null; }; @@ -150,8 +150,8 @@ export function NavMenu({ items }: NavMenuProps) { className="flex w-full items-center justify-between rounded-xl px-4 py-3 text-base font-medium text-slate-700 transition-colors active:bg-slate-100 dark:text-slate-200 dark:active:bg-slate-800" >
- - {item.label} + + {item.label}
- - {item.label} + + {item.label} ) : null; }; @@ -261,13 +261,13 @@ export function NavMenu({ items }: NavMenuProps) { >
- - {item.label} + + {item.label}