Created
May 14, 2025 13:55
-
-
Save bidah/c9a648590150e93fe60e0f4ce056909b to your computer and use it in GitHub Desktop.
youtube expo universal module
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Fontisto from "@expo/vector-icons/Fontisto"; | |
import React, { useState, useCallback, useEffect } from "react"; | |
import { View, ImageBackground, Pressable } from "react-native"; | |
import YoutubePlayerIframe from "react-native-youtube-iframe"; | |
import { useBoolean } from "@/hooks/use-boolean"; | |
const OverlayPlayerScreen = ({ | |
image, | |
setToggleOverlay, | |
}: { | |
image: string; | |
setToggleOverlay: { | |
setTrue: () => void; | |
setFalse: () => void; | |
toggle: () => void; | |
}; | |
}) => { | |
return ( | |
<ImageBackground | |
source={{ uri: image }} | |
className="absolute z-10 h-[210] w-full items-center justify-center" | |
imageStyle={{ | |
borderRadius: 20, | |
borderBottomLeftRadius: 0, | |
borderBottomRightRadius: 0, | |
}} | |
> | |
<Pressable | |
onPress={setToggleOverlay.setTrue} | |
className="h-[100%] w-[100%] items-center justify-center" | |
> | |
<View className="h-16 w-16 items-center justify-center rounded-full bg-black/70"> | |
<Fontisto name="play" size={24} color="white" style={{ left: 3 }} /> | |
</View> | |
</Pressable> | |
</ImageBackground> | |
); | |
}; | |
export function YoutubePlayer({ image, url }: { image: string; url: string }) { | |
const [playing, setPlaying] = useState(false); | |
const { value: toggleOverlay, ...toggleOverlayControls } = useBoolean(false); | |
const onStateChange = useCallback((state) => { | |
if (state === "ended") { | |
setPlaying(false); | |
} | |
}, []); | |
useEffect(() => { | |
if (toggleOverlay) { | |
setPlaying(true); | |
} | |
}, [toggleOverlay]); | |
return ( | |
<View> | |
{!toggleOverlay && ( | |
<OverlayPlayerScreen | |
image={image} | |
setToggleOverlay={toggleOverlayControls} | |
/> | |
)} | |
<YoutubePlayerIframe | |
webViewStyle={{ | |
borderTopLeftRadius: 20, | |
borderTopRightRadius: 20, | |
borderBottomLeftRadius: 0, | |
borderBottomRightRadius: 0, | |
}} | |
height={210} | |
play={playing} | |
videoId={ | |
url?.includes("youtu.be") | |
? url.split("/").pop() | |
: url?.split("v=")[1]?.split("&")[0] | |
} | |
onChangeState={onStateChange} | |
/> | |
</View> | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState, useCallback, useEffect, useRef } from "react"; | |
import { View, Alert, ImageBackground, Pressable } from "react-native"; | |
import YouTube, { type YouTubeProps } from "react-youtube"; | |
import Fontisto from "@expo/vector-icons/Fontisto"; | |
import { useBoolean } from "@/hooks/use-boolean"; | |
const OverlayPlayerScreen = ({ | |
image, | |
setToggleOverlay, | |
}: { | |
image: string; | |
setToggleOverlay: { | |
setTrue: () => void; | |
setFalse: () => void; | |
toggle: () => void; | |
}; | |
}) => { | |
return ( | |
<ImageBackground | |
source={{ uri: image }} | |
className="z-10 aspect-video bg-white" | |
resizeMode="contain" | |
imageStyle={{ | |
borderRadius: 20, | |
borderBottomLeftRadius: 0, | |
borderBottomRightRadius: 0, | |
}} | |
> | |
<Pressable | |
onPress={setToggleOverlay.setTrue} | |
className="h-[100%] w-[100%] items-center justify-center" | |
> | |
<View className="h-16 w-16 items-center justify-center rounded-full bg-black/70"> | |
<Fontisto name="play" size={24} color="white" style={{ left: 3 }} /> | |
</View> | |
</Pressable> | |
</ImageBackground> | |
); | |
}; | |
export function YoutubePlayer({ image, url }: { image: string; url: string }) { | |
const [playing, setPlaying] = useState(false); | |
const { value: toggleOverlay, ...toggleOverlayControls } = useBoolean(false); | |
const playerRef = useRef<YouTube>(null); | |
useEffect(() => { | |
if (toggleOverlay && playerRef.current) { | |
playerRef.current.internalPlayer.playVideo(); | |
setPlaying(true); | |
} | |
}, [toggleOverlay]); | |
const onReady: YouTubeProps["onReady"] = (event) => { | |
// No necesitamos hacer nada aquí ahora | |
}; | |
const onStateChange: YouTubeProps["onStateChange"] = (event) => { | |
if (event.data === YouTube.PlayerState.ENDED) { | |
setPlaying(false); | |
Alert.alert("Video has finished playing!"); | |
} | |
}; | |
const opts: YouTubeProps["opts"] = { | |
height: "100%", | |
width: "100%", | |
aspectRatio: 16 / 9, | |
playerVars: { | |
autoplay: playing ? 1 : 0, | |
}, | |
}; | |
return ( | |
<View> | |
{!toggleOverlay && ( | |
<OverlayPlayerScreen | |
image={image} | |
setToggleOverlay={toggleOverlayControls} | |
/> | |
)} | |
<YouTube | |
videoId={ | |
url?.includes("youtu.be") | |
? url.split("/").pop() | |
: url?.split("v=")[1]?.split("&")[0] | |
} | |
opts={opts} | |
onReady={onReady} | |
onStateChange={onStateChange} | |
className="aspect-video rounded-t-[20px]" | |
ref={playerRef} | |
/> | |
</View> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment