diff --git a/web/src/App.tsx b/web/src/App.tsx
index 89e196e..9ed031f 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -76,10 +76,21 @@ export function App() {
if (roomId && entered) recordarSala(roomId);
}, [roomId, entered]);
- // Pantalla 1: sin sala → crear o pegar link.
- if (!roomId) return ;
+ /**
+ * Sin sala en la URL se entra igual, a la Sala vacía.
+ *
+ * Antes había una portada con un botón de "crear una sala", y eso hacía dos
+ * cosas malas: quien ya tenía salas no las veía (viven en el menú, que solo
+ * existe dentro), así que creaba otra; y el único camino para llegar a
+ * cualquier lado era crear una, aunque solo quisieras volver a la de ayer.
+ * Cuatro de nueve salas acabaron vacías.
+ *
+ * Ahora se cae dentro con el menú a mano, y crear es un botón más.
+ */
+ if (!roomId) return ;
- // Pantalla 2: hay sala pero falta nombre.
+ // Hay sala pero falta decir cómo te llamas. Sigue haciendo falta para quien
+ // llega por un link que le pasaron: la sala necesita saber quién entró.
if (!entered) {
return (
;
}
-// ── Pantalla: crear / entrar a sala ────────────────────────────────────────
-
-function Landing() {
- const { t } = useTextos();
- const [busy, setBusy] = useState(false);
- const [pegando, setPegando] = useState(false);
- const [link, setLink] = useState("");
- const [error, setError] = useState(null);
-
- const nueva = async () => {
- setBusy(true);
- try {
- const id = await createRoom();
- window.location.hash = `#/sala/${id}`;
- } catch (e) {
- alert(t.noSePudoCrear + String(e));
- setBusy(false);
- }
- };
-
- /**
- * Entrar con lo que te pasó tu compa.
- *
- * Normalmente el link se abre y ya (el id vive en el hash), pero llega por
- * WhatsApp o Discord y a veces se copia mal, se parte, o te pasan solo el
- * nombre de la sala. Acepta las tres formas en vez de exigir la URL exacta.
- */
- const entrar = () => {
- const id = extraerRoomId(link);
- if (!id) {
- setError(t.noEncontreSala);
- return;
- }
- window.location.hash = `#/sala/${id}`;
- };
-
- return (
-
- );
-}
-
-/**
- * Saca el id de la sala de lo que sea que hayan pegado: la URL completa, solo el
- * fragmento `#/sala/x`, o el nombre pelón. Los ids son de la forma
- * `palabra-palabra-numero`.
- */
-function extraerRoomId(raw: string): string | null {
- const texto = raw.trim();
- if (!texto) return null;
- const enRuta = texto.match(/\/sala\/([\w-]+)/);
- if (enRuta) return enRuta[1];
- // Solo el nombre: debe parecer un id de sala, no una frase cualquiera.
- if (/^[a-z]+-[a-z]+-\d+$/i.test(texto)) return texto;
- return null;
-}
-
-// ── Pantalla: pedir nombre ─────────────────────────────────────────────────
function NamePrompt(props: {
roomId: string;
@@ -233,7 +152,12 @@ function NamePrompt(props: {
// ── La Sala ─────────────────────────────────────────────────────────────────
-function Sala({ roomId, name }: { roomId: string; name: string }) {
+/**
+ * La Sala. Con `roomId` en null se ve el mismo marco pero vacío: es lo que hay
+ * al entrar a Multi sin haber elegido sala, con el menú y el botón de crear a
+ * la mano.
+ */
+function Sala({ roomId, name }: { roomId: string | null; name: string }) {
const { t } = useTextos();
const [members, setMembers] = useState([]);
const [messages, setMessages] = useState([]);
@@ -247,6 +171,7 @@ function Sala({ roomId, name }: { roomId: string; name: string }) {
*/
const [nombre, setNombre] = useState(null);
const [editandoNombre, setEditandoNombre] = useState(false);
+ const [creandoSala, setCreandoSala] = useState(false);
/** Qué dice el botón de descargar ahora mismo. null = su texto normal. */
const [zipAviso, setZipAviso] = useState(null);
/**
@@ -333,6 +258,10 @@ function Sala({ roomId, name }: { roomId: string; name: string }) {
const proxyOrigin = new URL(SERVER_URL).origin;
useEffect(() => {
+ // Sin sala no hay a qué conectarse: la Sala vacía es solo el marco con el
+ // menú y el botón de crear.
+ if (!roomId) return;
+
const socket = connectSocket();
socketRef.current = socket;
@@ -598,6 +527,18 @@ function Sala({ roomId, name }: { roomId: string; name: string }) {
const copyLink = () => navigator.clipboard.writeText(window.location.href);
+ /** Crear otra sala y entrar a ella. El hash es lo que cambia de sala. */
+ const crearSala = async () => {
+ setCreandoSala(true);
+ try {
+ window.location.hash = `#/sala/${await createRoom()}`;
+ } catch (e) {
+ alert(t.noSePudoCrear + String(e));
+ } finally {
+ setCreandoSala(false);
+ }
+ };
+
/**
* Guardar el nombre nuevo de la sala.
*
@@ -679,9 +620,13 @@ function Sala({ roomId, name }: { roomId: string; name: string }) {
{/* Chat izquierda */}