diff --git a/src/app/globals.css b/src/app/globals.css
index dfd1b05..6d32303 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -338,6 +338,25 @@ a.btn-primary:visited {
display: block;
}
+.video-embed-container {
+ position: relative;
+ padding-bottom: 56.25%; /* 16:9 aspect ratio */
+ height: 0;
+ overflow: hidden;
+ border-radius: var(--radius-md);
+ margin-bottom: 12px;
+ border: 1px solid var(--border);
+ background: #000;
+}
+
+.video-embed-container iframe {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+}
+
.post-actions {
display: flex;
gap: 24px;
diff --git a/src/components/PostCard.tsx b/src/components/PostCard.tsx
index ae89e73..e653491 100644
--- a/src/components/PostCard.tsx
+++ b/src/components/PostCard.tsx
@@ -5,6 +5,7 @@ import Link from 'next/link';
import { HeartIcon, RepeatIcon, MessageIcon, FlagIcon, TrashIcon } from '@/components/Icons';
import { Post } from '@/lib/types';
import { useAuth } from '@/lib/contexts/AuthContext';
+import { VideoEmbed } from '@/components/VideoEmbed';
interface PostCardProps {
post: Post;
@@ -181,6 +182,10 @@ export function PostCard({ post, onLike, onRepost, onComment, onDelete, isDetail
)}
{post.linkPreviewUrl && (
+
+ )}
+
+ {post.linkPreviewUrl && !post.linkPreviewUrl.match(/(youtube\.com|youtu\.be|vimeo\.com)/) && (
{
+ const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
+ const match = url.match(regExp);
+ return (match && match[2].length === 11) ? match[2] : null;
+ };
+
+ const getVimeoId = (url: string) => {
+ const regExp = /(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/(?:[^\/]*)\/videos\/|album\/(?:\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/;
+ const match = url.match(regExp);
+ return match ? match[1] : null;
+ };
+
+ const youtubeId = getYouTubeId(url);
+ const vimeoId = getVimeoId(url);
+
+ if (youtubeId) {
+ return (
+
+
+
+ );
+ }
+
+ if (vimeoId) {
+ return (
+
+
+
+ );
+ }
+
+ return null;
+}