feat: Add video embedding for YouTube and Vimeo links in PostCard.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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 && (
|
||||
<VideoEmbed url={post.linkPreviewUrl} />
|
||||
)}
|
||||
|
||||
{post.linkPreviewUrl && !post.linkPreviewUrl.match(/(youtube\.com|youtu\.be|vimeo\.com)/) && (
|
||||
<a
|
||||
href={post.linkPreviewUrl}
|
||||
target="_blank"
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
'use client';
|
||||
|
||||
interface VideoEmbedProps {
|
||||
url: string;
|
||||
}
|
||||
|
||||
export function VideoEmbed({ url }: VideoEmbedProps) {
|
||||
const getYouTubeId = (url: string) => {
|
||||
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 (
|
||||
<div className="video-embed-container">
|
||||
<iframe
|
||||
src={`https://www.youtube.com/embed/${youtubeId}`}
|
||||
title="YouTube video player"
|
||||
frameBorder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (vimeoId) {
|
||||
return (
|
||||
<div className="video-embed-container">
|
||||
<iframe
|
||||
src={`https://player.vimeo.com/video/${vimeoId}`}
|
||||
title="Vimeo video player"
|
||||
frameBorder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture"
|
||||
allowFullScreen
|
||||
></iframe>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user