Spaces:
Running
Running
Update cointube.jsx
Browse files- cointube.jsx +27 -9
cointube.jsx
CHANGED
|
@@ -42,8 +42,11 @@ export default function App() {
|
|
| 42 |
const [authReady, setAuthReady] = useState(false);
|
| 43 |
const [userProfile, setUserProfile] = useState(null);
|
| 44 |
const [currentTab, setCurrentTab] = useState('ganar');
|
| 45 |
-
|
| 46 |
-
|
|
|
|
|
|
|
|
|
|
| 47 |
const [ytApiReady, setYtApiReady] = useState(false);
|
| 48 |
|
| 49 |
const playerRef = useRef(null);
|
|
@@ -111,23 +114,32 @@ export default function App() {
|
|
| 111 |
|
| 112 |
useEffect(() => {
|
| 113 |
if (!firebaseReady || !db) return;
|
|
|
|
| 114 |
const q = query(collection(db, 'videos'), orderBy('createdAt', 'desc'), limit(50));
|
| 115 |
const unsubscribe = onSnapshot(q, (snapshot) => {
|
| 116 |
const fetchedVideos = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
|
|
|
|
| 117 |
if (fetchedVideos.length > 0) {
|
| 118 |
setVideos(fetchedVideos);
|
| 119 |
-
|
|
|
|
| 120 |
const latestVideo = fetchedVideos[0];
|
| 121 |
setCurrentVideoId(latestVideo.videoId);
|
| 122 |
setCurrentVideoTitle(latestVideo.title);
|
| 123 |
initialLoadRef.current = false;
|
| 124 |
}
|
| 125 |
} else {
|
| 126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
}
|
| 128 |
});
|
| 129 |
return () => unsubscribe();
|
| 130 |
-
}, [firebaseReady]);
|
| 131 |
|
| 132 |
useEffect(() => {
|
| 133 |
if (!firebaseReady || !db) return;
|
|
@@ -202,7 +214,8 @@ export default function App() {
|
|
| 202 |
}, [startCoinInterval, stopCoinInterval, currentVideoId, userId]);
|
| 203 |
|
| 204 |
useEffect(() => {
|
| 205 |
-
|
|
|
|
| 206 |
playerRef.current = new window.YT.Player('player', {
|
| 207 |
height: '100%',
|
| 208 |
width: '100%',
|
|
@@ -370,11 +383,16 @@ export default function App() {
|
|
| 370 |
|
| 371 |
<main className={`${currentTab === 'ganar' ? 'flex' : 'hidden'} flex-1 flex-col lg:flex-row gap-6`}>
|
| 372 |
<div className="lg:w-2/3">
|
| 373 |
-
<div className="aspect-video bg-black rounded-lg overflow-hidden shadow-xl">
|
| 374 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
</div>
|
| 376 |
<div className="mt-3 p-3 bg-gray-800 rounded">
|
| 377 |
-
<h3 className="text-white font-medium">{currentVideoTitle}</h3>
|
| 378 |
</div>
|
| 379 |
</div>
|
| 380 |
<aside className="lg:w-1/3 flex flex-col gap-4 h-full overflow-hidden">
|
|
|
|
| 42 |
const [authReady, setAuthReady] = useState(false);
|
| 43 |
const [userProfile, setUserProfile] = useState(null);
|
| 44 |
const [currentTab, setCurrentTab] = useState('ganar');
|
| 45 |
+
|
| 46 |
+
// CAMBIO 1: Iniciamos en null para no mostrar el default mientras carga
|
| 47 |
+
const [currentVideoId, setCurrentVideoId] = useState(null);
|
| 48 |
+
const [currentVideoTitle, setCurrentVideoTitle] = useState(null);
|
| 49 |
+
|
| 50 |
const [ytApiReady, setYtApiReady] = useState(false);
|
| 51 |
|
| 52 |
const playerRef = useRef(null);
|
|
|
|
| 114 |
|
| 115 |
useEffect(() => {
|
| 116 |
if (!firebaseReady || !db) return;
|
| 117 |
+
// La consulta ya ordena por fecha descendente (el más nuevo primero)
|
| 118 |
const q = query(collection(db, 'videos'), orderBy('createdAt', 'desc'), limit(50));
|
| 119 |
const unsubscribe = onSnapshot(q, (snapshot) => {
|
| 120 |
const fetchedVideos = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
|
| 121 |
+
|
| 122 |
if (fetchedVideos.length > 0) {
|
| 123 |
setVideos(fetchedVideos);
|
| 124 |
+
// CAMBIO 2: Si es la carga inicial O si no hay video seleccionado aún
|
| 125 |
+
if (initialLoadRef.current || !currentVideoId) {
|
| 126 |
const latestVideo = fetchedVideos[0];
|
| 127 |
setCurrentVideoId(latestVideo.videoId);
|
| 128 |
setCurrentVideoTitle(latestVideo.title);
|
| 129 |
initialLoadRef.current = false;
|
| 130 |
}
|
| 131 |
} else {
|
| 132 |
+
// Solo usamos el default si NO hay videos en la base de datos
|
| 133 |
+
setVideos([{ id: '1', title: DEFAULT_VIDEO_TITLE, videoId: DEFAULT_VIDEO_ID }]);
|
| 134 |
+
if (initialLoadRef.current || !currentVideoId) {
|
| 135 |
+
setCurrentVideoId(DEFAULT_VIDEO_ID);
|
| 136 |
+
setCurrentVideoTitle(DEFAULT_VIDEO_TITLE);
|
| 137 |
+
initialLoadRef.current = false;
|
| 138 |
+
}
|
| 139 |
}
|
| 140 |
});
|
| 141 |
return () => unsubscribe();
|
| 142 |
+
}, [firebaseReady, currentVideoId]); // Agregamos currentVideoId a dependencias para el chequeo de seguridad
|
| 143 |
|
| 144 |
useEffect(() => {
|
| 145 |
if (!firebaseReady || !db) return;
|
|
|
|
| 214 |
}, [startCoinInterval, stopCoinInterval, currentVideoId, userId]);
|
| 215 |
|
| 216 |
useEffect(() => {
|
| 217 |
+
// CAMBIO 3: Aseguramos que currentVideoId exista antes de inicializar el player
|
| 218 |
+
if (ytApiReady && userId && !playerRef.current && currentVideoId) {
|
| 219 |
playerRef.current = new window.YT.Player('player', {
|
| 220 |
height: '100%',
|
| 221 |
width: '100%',
|
|
|
|
| 383 |
|
| 384 |
<main className={`${currentTab === 'ganar' ? 'flex' : 'hidden'} flex-1 flex-col lg:flex-row gap-6`}>
|
| 385 |
<div className="lg:w-2/3">
|
| 386 |
+
<div className="aspect-video bg-black rounded-lg overflow-hidden shadow-xl flex items-center justify-center">
|
| 387 |
+
{/* CAMBIO 4: Renderizado condicional del player */}
|
| 388 |
+
{currentVideoId ? (
|
| 389 |
+
<div id="player" className="w-full h-full"></div>
|
| 390 |
+
) : (
|
| 391 |
+
<div className="text-gray-500 animate-pulse">Cargando último video...</div>
|
| 392 |
+
)}
|
| 393 |
</div>
|
| 394 |
<div className="mt-3 p-3 bg-gray-800 rounded">
|
| 395 |
+
<h3 className="text-white font-medium">{currentVideoTitle || "Cargando..."}</h3>
|
| 396 |
</div>
|
| 397 |
</div>
|
| 398 |
<aside className="lg:w-1/3 flex flex-col gap-4 h-full overflow-hidden">
|