128 lines
4.3 KiB
TypeScript
128 lines
4.3 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
import { ThemeProvider } from "./ThemeProvider";
|
|
import Sidebar from "./Sidebar";
|
|
import Header from "./Header";
|
|
import styles from "./Studio.module.css";
|
|
import { StudioPortal } from "../features/studio";
|
|
|
|
const Studio: React.FC = () => {
|
|
const [tokenData, setTokenData] = useState<{
|
|
token?: string;
|
|
url?: string;
|
|
} | null>(null);
|
|
|
|
useEffect(() => {
|
|
const userName = localStorage.getItem("avanzacast_user") || "Usuario";
|
|
const roomName =
|
|
localStorage.getItem("avanzacast_room") || "avanzacast-studio";
|
|
localStorage.setItem("avanzacast_user", userName);
|
|
localStorage.setItem("avanzacast_room", roomName);
|
|
|
|
// Request session token via backend API: POST /api/session then GET /api/session/:id
|
|
(async () => {
|
|
try {
|
|
// Create session (POST)
|
|
const createResp = await fetch("/api/session", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ room: roomName, username: userName }),
|
|
credentials: "include",
|
|
});
|
|
if (!createResp.ok) {
|
|
console.warn("studio session create failed", createResp.status);
|
|
return;
|
|
}
|
|
const created = await createResp.json();
|
|
const sessionId = created && created.id;
|
|
if (!sessionId) {
|
|
console.warn("studio session create returned no id", created);
|
|
return;
|
|
}
|
|
// Fetch full session data (token and url)
|
|
const fetchResp = await fetch(
|
|
`/api/session/${encodeURIComponent(sessionId)}`,
|
|
{ method: "GET", credentials: "include" },
|
|
);
|
|
if (!fetchResp.ok) {
|
|
console.warn("failed fetching session data", fetchResp.status);
|
|
return;
|
|
}
|
|
const data = await fetchResp.json();
|
|
// expected { token, url }
|
|
setTokenData({ token: data.token, url: data.url });
|
|
return;
|
|
} catch (e) {
|
|
console.warn("failed requesting studio session", e);
|
|
}
|
|
})();
|
|
}, []);
|
|
|
|
// New: optionally use the LiveKit React components wrapper (dynamically imported)
|
|
const useLiveKitComponents =
|
|
(import.meta.env.VITE_USE_LIVEKIT_COMPONENTS as string) === "1";
|
|
const [LKPortal, setLKPortal] = useState<any | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!useLiveKitComponents)
|
|
return; // dynamic import so bundler only includes it when requested
|
|
(async () => {
|
|
try {
|
|
const mod = await import(
|
|
"../features/studio/StudioPortalWithComponents"
|
|
);
|
|
setLKPortal(mod.default || null);
|
|
} catch (e) {
|
|
console.warn("Failed to load StudioPortalWithComponents", e);
|
|
}
|
|
})();
|
|
}, [useLiveKitComponents]);
|
|
|
|
return (
|
|
<ThemeProvider>
|
|
<div className={styles.studioContainer}>
|
|
<Sidebar activeLink="studio" />
|
|
<div className={styles.mainContent}>
|
|
<Header />
|
|
<main className={styles.studioMain}>
|
|
{tokenData ? (
|
|
useLiveKitComponents && LKPortal ? (
|
|
<LKPortal
|
|
serverUrl={
|
|
tokenData.url ||
|
|
(import.meta.env.VITE_LIVEKIT_WS_URL as string) ||
|
|
""
|
|
}
|
|
token={tokenData.token || ""}
|
|
/>
|
|
) : (
|
|
<StudioPortal
|
|
serverUrl={
|
|
tokenData.url ||
|
|
(import.meta.env.VITE_LIVEKIT_WS_URL as string) ||
|
|
""
|
|
}
|
|
token={tokenData.token || ""}
|
|
/>
|
|
)
|
|
) : (
|
|
<div className="flex items-center justify-center min-h-screen">
|
|
<div className="text-center">
|
|
<div className="inline-block h-12 w-12 animate-spin rounded-full border-4 border-solid border-blue-500 border-r-transparent mb-4"></div>
|
|
<h2 className="text-xl font-semibold">
|
|
Preparando tu estudio...
|
|
</h2>
|
|
<p className="text-gray-500 mt-2">
|
|
Solicitando credenciales seguras
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</main>
|
|
</div>
|
|
</div>
|
|
</ThemeProvider>
|
|
);
|
|
};
|
|
|
|
export default Studio;
|