diff --git a/.vscode/settings.json b/.vscode/settings.json index e16279b..7b349b8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,7 @@ "DOCKERHUB", "formspree", "geist", - "netconf" + "netconf", + "Youtube" ] } \ No newline at end of file diff --git a/app/[locale]/community/CommunityContent.tsx b/app/[locale]/community/CommunityContent.tsx index 377c568..ded53de 100644 --- a/app/[locale]/community/CommunityContent.tsx +++ b/app/[locale]/community/CommunityContent.tsx @@ -4,13 +4,33 @@ import { useState } from "react" import Image from "next/image" import { Badge } from "@/components/ui/badge" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog" -import { ExternalLink, Github, Users, Calendar, Award, Mic, MapPin, Heart } from "lucide-react" +import { ExternalLink, Github, Users, Calendar, Award, Mic, MapPin, Heart, Youtube } from "lucide-react" import LottieAnimation from "@/components/LottieAnimation" import { Event } from "@/types/Event" import { speakingAndEvents } from "@/data/events" import { shimmerBlurDataURL } from "@/lib/image" import { useTranslations } from "next-intl" +function getYoutubeEmbedUrl(url: string): string | null { + try { + const parsed = new URL(url); + const host = parsed.hostname.replace(/^www\./, ""); + let id: string | null = null; + if (host === "youtu.be") { + id = parsed.pathname.slice(1); + } else if (host.endsWith("youtube.com") || host.endsWith("youtube-nocookie.com")) { + if (parsed.pathname === "/watch") { + id = parsed.searchParams.get("v"); + } else if (parsed.pathname.startsWith("/embed/") || parsed.pathname.startsWith("/shorts/")) { + id = parsed.pathname.split("/")[2] ?? null; + } + } + return id ? `https://www.youtube-nocookie.com/embed/${id}` : null; + } catch { + return null; + } +} + export default function CommunityContent() { const [selectedEvent, setSelectedEvent] = useState(null); const t = useTranslations("Community"); @@ -174,18 +194,18 @@ export default function CommunityContent() { {selectedEvent.role} -
- {selectedEvent.title} -
-
+
+ {selectedEvent.title} +
+ {/* Meta Info */} {(selectedEvent.location || selectedEvent.startDate || selectedEvent.frequency || selectedEvent.year) && (
@@ -247,6 +267,34 @@ export default function CommunityContent() {
)} + {/* Videos */} + {selectedEvent.videos && selectedEvent.videos.length > 0 && ( +
+

+ + {t('dialog.videos')} +

+
+ {selectedEvent.videos.map((video, idx) => { + const embedUrl = getYoutubeEmbedUrl(video); + if (!embedUrl) return null; + return ( +
+