import { useEffect, useMemo, useRef, useState } from "react" let apiPromise: Promise | null = null /** Charge l'API IFrame YouTube une seule fois. */ function loadYoutubeApi(): Promise { if (window.YT?.Player) { return Promise.resolve() } if (apiPromise) { return apiPromise } apiPromise = new Promise((resolve) => { const previous = window.onYouTubeIframeAPIReady window.onYouTubeIframeAPIReady = () => { previous?.() resolve() } const tag = document.createElement("script") tag.src = "https://www.youtube.com/iframe_api" document.head.appendChild(tag) }) return apiPromise } export interface YoutubeApi { play: () => void pause: () => void seek: (seconds: number) => void time: () => number duration: () => number } /** * Crée un lecteur YouTube pour `youtubeId`. Renvoie un ref à poser sur un div * hôte, l'état "prêt", et une API impérative (play/pause/seek/time). */ export function useYoutube(youtubeId: string) { const hostRef = useRef(null) const playerRef = useRef(null) const [ready, setReady] = useState(false) useEffect(() => { let cancelled = false const host = hostRef.current if (!host) { return } setReady(false) // YT remplace l'élément fourni par une iframe → on lui donne un enfant jetable // pour que React ne gère jamais ce nœud. const inner = document.createElement("div") host.appendChild(inner) loadYoutubeApi().then(() => { if (cancelled || !window.YT) { return } playerRef.current = new window.YT.Player(inner, { videoId: youtubeId, playerVars: { autoplay: 0, controls: 0, disablekb: 1, modestbranding: 1, rel: 0, playsinline: 1, }, events: { onReady: () => { if (!cancelled) { setReady(true) } }, }, }) }) return () => { cancelled = true playerRef.current?.destroy() playerRef.current = null host.replaceChildren() } }, [youtubeId]) const api = useMemo( () => ({ play: () => playerRef.current?.playVideo(), pause: () => playerRef.current?.pauseVideo(), seek: (seconds) => playerRef.current?.seekTo(seconds, true), time: () => playerRef.current?.getCurrentTime() ?? 0, duration: () => playerRef.current?.getDuration() ?? 0, }), [] ) return { hostRef, ready, api } }