salomonsky commited on
Commit
ed8b4af
·
verified ·
1 Parent(s): 6358cbc

Update cointube.jsx

Browse files
Files changed (1) hide show
  1. cointube.jsx +57 -49
cointube.jsx CHANGED
@@ -22,41 +22,9 @@ import {
22
  limit
23
  } from 'firebase/firestore';
24
 
25
- // --- CONFIGURACIÓN DE FIREBASE (JSON PARSER) ---
26
  let app, auth, db;
27
 
28
- try {
29
- // 1. Intentamos leer la variable de entorno
30
- const configRaw = import.meta.env.VITE_FIREBASE_CONFIG;
31
-
32
- let firebaseConfig;
33
-
34
- if (configRaw) {
35
- // 2. Si existe, la parseamos de JSON a Objeto
36
- firebaseConfig = JSON.parse(configRaw);
37
- } else {
38
- // 3. Fallback de seguridad o error visible en consola
39
- console.error("FALTA CONFIGURACIÓN: La variable VITE_FIREBASE_CONFIG está vacía.");
40
- // Opcional: Valores por defecto hardcodeados si todo falla
41
- firebaseConfig = {
42
- apiKey: "AIzaSyCwJjVJGuOmA_PKRbaTnQDrK-Q07NI_utc",
43
- authDomain: "insights-5c2d6.firebaseapp.com",
44
- projectId: "insights-5c2d6",
45
- storageBucket: "insights-5c2d6.firebasestorage.app",
46
- messagingSenderId: "61805724903",
47
- appId: "1:61805724903:web:0f3771dc5cd44416600e42"
48
- };
49
- }
50
-
51
- app = initializeApp(firebaseConfig);
52
- auth = getAuth(app);
53
- db = getFirestore(app);
54
- console.log("Firebase inicializado correctamente.");
55
-
56
- } catch (error) {
57
- console.error("ERROR CRÍTICO AL INICIAR FIREBASE:", error);
58
- }
59
-
60
  // --- Constantes del Sistema ---
61
  const ADMIN_EMAIL = "photonicsupernova@gmail.com";
62
  const VIDEO_COST = 10000;
@@ -65,7 +33,11 @@ const DEFAULT_VIDEO_TITLE = "Pelicula Completa";
65
 
66
  export default function App() {
67
 
68
- // --- Estados ---
 
 
 
 
69
  const [videos, setVideos] = useState([]);
70
  const [leaderboard, setLeaderboard] = useState([]);
71
  const [user, setUser] = useState(null);
@@ -80,15 +52,41 @@ export default function App() {
80
  const playerRef = useRef(null);
81
  const coinIntervalRef = useRef(null);
82
  const localCoinBufferRef = useRef(0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
- // --- Efectos ---
85
 
86
  // 1. Auth
87
  useEffect(() => {
88
- if (!auth) {
89
- setAuthReady(true);
90
- return;
91
- }
92
  const unsubscribeAuth = onAuthStateChanged(auth, (user) => {
93
  if (user) {
94
  setUser(user);
@@ -101,11 +99,11 @@ export default function App() {
101
  setAuthReady(true);
102
  });
103
  return () => unsubscribeAuth();
104
- }, []);
105
 
106
  // 2. Perfil de Usuario
107
  useEffect(() => {
108
- if (!userId || !db) return;
109
  const profileRef = doc(db, 'users', userId);
110
  const unsubscribeProfile = onSnapshot(profileRef, (docSnap) => {
111
  if (docSnap.exists()) {
@@ -121,11 +119,11 @@ export default function App() {
121
  }
122
  }, (error) => console.error("Error listening to profile:", error));
123
  return () => unsubscribeProfile();
124
- }, [userId, user]);
125
 
126
  // 3. Cargar Lista de Videos
127
  useEffect(() => {
128
- if (!db) return;
129
  const q = query(collection(db, 'videos'), orderBy('createdAt', 'desc'), limit(20));
130
  const unsubscribe = onSnapshot(q, (snapshot) => {
131
  const fetchedVideos = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
@@ -139,18 +137,18 @@ export default function App() {
139
  }
140
  });
141
  return () => unsubscribe();
142
- }, []);
143
 
144
  // 4. LEADERBOARD
145
  useEffect(() => {
146
- if (!db) return;
147
  const q = query(collection(db, 'users'), orderBy('coins', 'desc'), limit(20));
148
  const unsubscribe = onSnapshot(q, (snapshot) => {
149
  const usersList = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
150
  setLeaderboard(usersList);
151
  });
152
  return () => unsubscribe();
153
- }, []);
154
 
155
  // 5. API YouTube
156
  useEffect(() => {
@@ -252,12 +250,22 @@ export default function App() {
252
  await signOut(auth);
253
  };
254
 
255
- // --- Renderizado de Carga ---
256
- if (!authReady) {
 
 
 
 
 
 
 
 
257
  return (
258
  <div className="flex flex-col items-center justify-center h-full w-full">
259
  <div className="spinner mb-4"></div>
260
- <p className="text-lg text-gray-400">Conectando...</p>
 
 
261
  </div>
262
  );
263
  }
 
22
  limit
23
  } from 'firebase/firestore';
24
 
25
+ // --- Variables Globales (se llenarán después) ---
26
  let app, auth, db;
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  // --- Constantes del Sistema ---
29
  const ADMIN_EMAIL = "photonicsupernova@gmail.com";
30
  const VIDEO_COST = 10000;
 
33
 
34
  export default function App() {
35
 
36
+ // --- Estado de Inicialización ---
37
+ const [firebaseReady, setFirebaseReady] = useState(false);
38
+ const [configError, setConfigError] = useState(null);
39
+
40
+ // --- Estados de la App ---
41
  const [videos, setVideos] = useState([]);
42
  const [leaderboard, setLeaderboard] = useState([]);
43
  const [user, setUser] = useState(null);
 
52
  const playerRef = useRef(null);
53
  const coinIntervalRef = useRef(null);
54
  const localCoinBufferRef = useRef(0);
55
+
56
+ // --- EFECTO 0: OBTENER CONFIGURACIÓN DEL SERVIDOR (RUNTIME) ---
57
+ useEffect(() => {
58
+ const initFirebase = async () => {
59
+ try {
60
+ // 1. Pedimos la config al servidor
61
+ const response = await fetch('/api/config');
62
+ if (!response.ok) throw new Error("Falló la carga de configuración");
63
+
64
+ const config = await response.json();
65
+
66
+ // 2. Iniciamos Firebase con los datos recibidos
67
+ if (!app) {
68
+ app = initializeApp(config);
69
+ auth = getAuth(app);
70
+ db = getFirestore(app);
71
+ console.log("Firebase conectado vía Secret Runtime");
72
+ }
73
+ setFirebaseReady(true);
74
+
75
+ } catch (error) {
76
+ console.error("Error crítico:", error);
77
+ setConfigError("No se pudo conectar con el servidor de autenticación.");
78
+ }
79
+ };
80
+
81
+ initFirebase();
82
+ }, []);
83
 
84
+ // --- Efectos (Solo corren si firebaseReady es true) ---
85
 
86
  // 1. Auth
87
  useEffect(() => {
88
+ if (!firebaseReady || !auth) return;
89
+
 
 
90
  const unsubscribeAuth = onAuthStateChanged(auth, (user) => {
91
  if (user) {
92
  setUser(user);
 
99
  setAuthReady(true);
100
  });
101
  return () => unsubscribeAuth();
102
+ }, [firebaseReady]);
103
 
104
  // 2. Perfil de Usuario
105
  useEffect(() => {
106
+ if (!firebaseReady || !userId || !db) return;
107
  const profileRef = doc(db, 'users', userId);
108
  const unsubscribeProfile = onSnapshot(profileRef, (docSnap) => {
109
  if (docSnap.exists()) {
 
119
  }
120
  }, (error) => console.error("Error listening to profile:", error));
121
  return () => unsubscribeProfile();
122
+ }, [userId, user, firebaseReady]);
123
 
124
  // 3. Cargar Lista de Videos
125
  useEffect(() => {
126
+ if (!firebaseReady || !db) return;
127
  const q = query(collection(db, 'videos'), orderBy('createdAt', 'desc'), limit(20));
128
  const unsubscribe = onSnapshot(q, (snapshot) => {
129
  const fetchedVideos = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
 
137
  }
138
  });
139
  return () => unsubscribe();
140
+ }, [firebaseReady]);
141
 
142
  // 4. LEADERBOARD
143
  useEffect(() => {
144
+ if (!firebaseReady || !db) return;
145
  const q = query(collection(db, 'users'), orderBy('coins', 'desc'), limit(20));
146
  const unsubscribe = onSnapshot(q, (snapshot) => {
147
  const usersList = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
148
  setLeaderboard(usersList);
149
  });
150
  return () => unsubscribe();
151
+ }, [firebaseReady]);
152
 
153
  // 5. API YouTube
154
  useEffect(() => {
 
250
  await signOut(auth);
251
  };
252
 
253
+ // --- Renderizado de Carga / Error ---
254
+ if (configError) {
255
+ return (
256
+ <div className="flex flex-col items-center justify-center h-full w-full text-red-500">
257
+ <p>⚠️ {configError}</p>
258
+ </div>
259
+ );
260
+ }
261
+
262
+ if (!firebaseReady || !authReady) {
263
  return (
264
  <div className="flex flex-col items-center justify-center h-full w-full">
265
  <div className="spinner mb-4"></div>
266
+ <p className="text-lg text-gray-400">
267
+ {!firebaseReady ? "Obteniendo configuración segura..." : "Conectando usuario..."}
268
+ </p>
269
  </div>
270
  );
271
  }