From d015b6e13251b7be53c541c70d72e1e51ac64d27 Mon Sep 17 00:00:00 2001 From: ErickHub192 Date: Sun, 6 Sep 2026 17:40:56 -0600 Subject: [PATCH] Los valores de las variables se ven en puntos El panel guarda credenciales y las pintaba en claro: con alguien compartiendo pantalla o mirando de reojo, ahi va la llave de la base. Se enmascara lo que ya estaba guardado, no lo que se esta escribiendo. Una fila recien agregada nace a la vista, porque al pegar una credencial hay que poder comprobar que se pego completa. Al guardar y al reabrir el panel, todo vuelve a taparse. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01L1nFf8JaKeGedJ6RaZQYZ8 --- web/src/EnvPanel.tsx | 67 +++++++++++++++++++++++++++++++++++++++++++- web/src/i18n.tsx | 4 +++ web/src/styles.css | 20 +++++++++++++ 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/web/src/EnvPanel.tsx b/web/src/EnvPanel.tsx index 5e0f88a..58316c8 100644 --- a/web/src/EnvPanel.tsx +++ b/web/src/EnvPanel.tsx @@ -31,12 +31,22 @@ export function EnvPanel({ roomId }: { roomId: string }) { const [vars, setVars] = useState([]); const [guardando, setGuardando] = useState(false); const [guardado, setGuardado] = useState(false); + /** + * Qué valores están a la vista, por índice de fila. + * + * Se enmascara lo que se leyó del server, no lo que se está escribiendo: si + * ocultara mientras alguien pega una credencial, no habría manera de + * comprobar que se pegó completa, que es justo cuando más importa verla. + */ + const [visibles, setVisibles] = useState>(new Set()); const cajaRef = useRef(null); // Se leen al abrir y no al montar: son de la sala, así que pueden haber // cambiado por otra persona desde la última vez. useEffect(() => { if (!abierto) return; + // Cada apertura empieza tapada, aunque la vez pasada se hubiera revelado. + setVisibles(new Set()); fetch(`${SERVER_URL}/rooms/${roomId}/env`) .then((r) => (r.ok ? r.json() : null)) .then((d: { variables: Variable[] } | null) => d && setVars(d.variables)) @@ -68,14 +78,36 @@ export function EnvPanel({ roomId }: { roomId: string }) { const quitar = (i: number) => { setVars((prev) => prev.filter((_, j) => j !== i)); + // Las filas se identifican por posición, así que borrar una corre a las de + // abajo: sin esto, tapar la 2 acabaría destapando la 3. + setVisibles((prev) => { + const s = new Set(); + for (const j of prev) { + if (j < i) s.add(j); + else if (j > i) s.add(j - 1); + } + return s; + }); setGuardado(false); }; const agregar = () => { - setVars((prev) => [...prev, { nombre: "", valor: "" }]); + setVars((prev) => { + // La fila nueva nace a la vista: es la que se está por escribir. + setVisibles((v) => new Set(v).add(prev.length)); + return [...prev, { nombre: "", valor: "" }]; + }); setGuardado(false); }; + const alternarVisible = (i: number) => { + setVisibles((prev) => { + const s = new Set(prev); + if (!s.delete(i)) s.add(i); + return s; + }); + }; + const guardar = async () => { setGuardando(true); try { @@ -92,6 +124,9 @@ export function EnvPanel({ roomId }: { roomId: string }) { // Se pinta lo que el server dejó, no lo que se escribió: si descartó un // nombre inválido, hay que verlo aquí y no descubrirlo cuando la app falle. setVars(d.variables); + // Ya guardadas, se tapan: dejarlas a la vista es lo que acaba en una + // pantalla compartida un rato después. + setVisibles(new Set()); setGuardado(true); } catch (e) { alert(t.envNoSePudo + String(e)); @@ -124,11 +159,21 @@ export function EnvPanel({ roomId }: { roomId: string }) { /> cambiar(i, "valor", e.target.value)} spellCheck={false} + autoComplete="off" /> +