diff --git a/src/components/banner.tsx b/src/components/banner.tsx index 3ed6436..d3e3abf 100644 --- a/src/components/banner.tsx +++ b/src/components/banner.tsx @@ -1,16 +1,55 @@ import { Link, useLocation } from "react-router-dom"; import { Swiper, SwiperSlide } from "swiper/react"; import { Autoplay, EffectFade } from "swiper/modules"; +import type { Swiper as SwiperType } from "swiper"; import "swiper/css"; import "swiper/css/effect-fade"; import styles from "./Banner.module.css"; -import { useMemo } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useStore } from "@/store"; import type { BannerConfig, NavItem, NavChild } from "@/type"; import ScrollReveal from "@/components/ScrollReveal"; const FALLBACK_GRADIENT = "linear-gradient(135deg, #1a2a4a 0%, #2d4a7c 100%)"; +const VIDEO_EXT = ["mp4", "webm", "ogg"]; + +function mediaExtension(url: string) { + const path = url.split("?")[0] ?? ""; + return path.split(".").pop()?.toLowerCase() ?? ""; +} + +function isVideoUrl(url: string) { + return VIDEO_EXT.includes(mediaExtension(url)); +} + +function BannerSlideVideo({ + src, + active, + onEnded, + className, +}: { + src: string; + active: boolean; + onEnded: () => void; + className: string; +}) { + const ref = useRef(null); + useEffect(() => { + const v = ref.current; + if (!v) return; + if (active) { + v.currentTime = 0; + void v.play().catch(() => {}); + } else { + v.pause(); + } + }, [active, src]); + return ( +