Der Anrufkasten zeigt, WER dran ist -- nicht dreimal "Verbunden"
Filipe, zu Screen 1: "wenn ich anrufe soll das auch viel besser geiler und spezieller aussehen aber es soll nicht raushaengen." Erst gemessen: Es haengt nichts raus. Der Kasten ist 374 px am Handy, 340 am Rechner, 72 Teile geprueft, kein einziges ueber dem Rand. Die Optik war also gar nicht der Mangel -- zwei andere Dinge waren es. 1. DER NAME DES ANRUFERS GING IMMER VERLOREN. `wer(raumName || "Anruf")` lief VOR `kastenBauen()`. Das Element #anruf-wer gab es zu dem Zeitpunkt noch nicht, die Zuweisung lief ins Leere, und oben stand bei jedem Anruf das Wort "Anruf". Die Reihenfolge ist umgedreht: erst bauen, dann beschriften. 2. IN EINEM ANRUF OHNE VIDEO STAND JE PERSON DAS WORT "Verbunden". Bei dreien dreimal dasselbe Wort -- und man sah nicht, WER dabei war. In einer Gruppe ist genau das die Frage: Ist Kessi schon drin? Jetzt steht dort ein Kreis mit den Anfangsbuchstaben und der echte Name; waehrend es klingelt ein wartendes Gesicht mit dem Namen dessen, den man anruft. Vorher war die Flaeche in dieser Sekunde leer, und ein leerer Kasten mit "Es klingelt ..." sieht aus wie einer, der haengt -- ausgerechnet im unsichersten Moment. Der Name kommt NICHT aus einer Abfrage. Wer anruft, bekannt beim Start nur sich selbst; alle weiteren kommen ausschliesslich ueber das Ereignis "dabei", und genau dort fehlte das Einsammeln. Deshalb sah der ANRUFER unter jedem Kreis "Jemand" -- die Angerufenen nicht. UND DIE PRUEFUNG WAR ZU NACHSICHTIG. Sie verlangte einen Namen "laenger als ein Zeichen"; der Rueckfalltext "Jemand" ist sechs Zeichen lang und kam damit durch. Gruen, waehrend der Hauptfall kaputt war. Die zweite Fassung verglich gegen eine abgeschriebene Namensliste -- die nannte "Jonas, Luna, Mara, Pat", angelegt werden aber "Filipe, Rieke, Kessi, Tili", und der Kommentar daneben behauptete schon da, sie sei abgeleitet. Jetzt ist sie es wirklich: Die Namen werden beim Anlegen eingesammelt, und geprueft wird, dass jeder GENAU DIE BEIDEN ANDEREN sieht -- nicht "irgendeinen echten Namen", denn der eigene Name im eigenen Kasten waere auch einer. pruef-anruf: 127 Pruefungen, 0 Fehler. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -251,6 +251,82 @@
|
||||
* klingelt …" -- man sah nicht, wen man anruft. */
|
||||
const wer = (text) => { const w = $('anruf-wer'); if (w) w.textContent = text; };
|
||||
|
||||
/* =====================================================================
|
||||
WER IST DRAN -- MIT NAMEN UND GESICHT (20.09.2026)
|
||||
|
||||
Filipe, zur Anrufbox: „die soll auch viel besser geiler und
|
||||
spezieller aussehen, aber nicht so raushaengen."
|
||||
|
||||
DER GROESSTE MANGEL WAR KEIN SCHOENHEITSFEHLER. In einem Anruf
|
||||
ohne Video stand unter dem Kasten das Wort „Verbunden" -- einmal
|
||||
je Person. Bei dreien stand es dreimal, und man sah nicht, WER
|
||||
verbunden war. In einer Gruppe ist genau das die Frage: Ist Luna
|
||||
schon drin? Hoert der Modi mit?
|
||||
|
||||
Es gibt keine Profilbilder im Anruf -- die Sitzung liefert sie
|
||||
nicht mit, und sie dafuer durch eine Abfrage zu holen, die auf
|
||||
JEDER Seite laeuft, waere an der falschen Stelle gespart und an
|
||||
der falschen teuer. Stattdessen dasselbe Mittel wie im Chat: der
|
||||
Anfangsbuchstabe in einem Kreis. Er ist sofort da, kostet nichts
|
||||
und unterscheidet in einer Gruppe von drei bis fuenf Leuten
|
||||
zuverlaessig.
|
||||
|
||||
WAEHREND ES KLINGELT steht dort, WEN man anruft -- gross, mit
|
||||
einem ruhigen Puls. Vorher war die Flaeche in diesem Moment leer,
|
||||
und ein leerer Kasten mit „Es klingelt ..." sieht aus wie einer,
|
||||
der haengt. Es ist die Sekunde, in der man am unsichersten ist.
|
||||
===================================================================== */
|
||||
|
||||
/** Die Namen aller, die im Anruf sind -- id -> Name.
|
||||
*
|
||||
* Auf dem Anruf selbst und nicht daneben: Endet er, ist die Karte
|
||||
* mit ihm weg. Eine Karte, die einen Anruf ueberlebt, zeigt beim
|
||||
* naechsten Namen von gestern. */
|
||||
function namenMerken(liste) {
|
||||
if (!anruf || !Array.isArray(liste)) return;
|
||||
if (!anruf.namen) anruf.namen = new Map();
|
||||
for (const w of liste) if (w && w.id != null) anruf.namen.set(w.id, w.name || '');
|
||||
}
|
||||
|
||||
/** Ein bis zwei Buchstaben aus einem Namen -- dieselbe Regel wie im
|
||||
* Chat: bei zwei Wörtern die Anfangsbuchstaben beider, sonst der
|
||||
* erste. „Luna Sanchez" -> LS, „Dogi" -> D. */
|
||||
function zeichenVon(name) {
|
||||
const teile = String(name || '').trim().split(/\s+/).filter(Boolean);
|
||||
if (!teile.length) return '?';
|
||||
if (teile.length === 1) return teile[0][0].toUpperCase();
|
||||
return (teile[0][0] + teile[teile.length - 1][0]).toUpperCase();
|
||||
}
|
||||
|
||||
/** Ein Gesichtsfeld: Kreis mit Buchstaben, Name darunter.
|
||||
*
|
||||
* `lage` ist 'da' (verbunden) oder 'wartet' (klingelt noch) -- das
|
||||
* Stilblatt macht daraus den Unterschied zwischen ruhig und
|
||||
* pulsierend. Der Zustand steht auch im Text darunter: Ein Puls
|
||||
* allein ist nichts, was ein Vorleseprogramm ansagen kann. */
|
||||
function gesichtsfeld(name, lage, stumm) {
|
||||
const k = el('div', 'anruf__gesicht');
|
||||
k.dataset.lage = lage;
|
||||
const kreis = el('span', 'anruf__kreis', zeichenVon(name));
|
||||
/* Der Kreis traegt zwei Buchstaben -- als Bild, nicht als Text.
|
||||
Ein Vorleseprogramm soll „Luna Sanchez, klingelt" sagen und
|
||||
nicht „L S". */
|
||||
kreis.setAttribute('aria-hidden', 'true');
|
||||
k.append(kreis);
|
||||
if (stumm) {
|
||||
/* KEINE WIEDERHOLUNG DESSEN, WAS DIREKT DARUEBER STEHT.
|
||||
Beim Anruf zu zweit sagt die Kopfzeile schon „Luna Sanchez" und
|
||||
„Es klingelt ..." -- beides zwei Zeilen tiefer noch einmal
|
||||
hinzuschreiben macht den Kasten hoeher und sagt nichts dazu.
|
||||
Fuer Vorleseprogramme bleibt der Name trotzdem am Element. */
|
||||
k.setAttribute('aria-label', `${name || 'Jemand'} – klingelt`);
|
||||
return k;
|
||||
}
|
||||
k.append(el('span', 'anruf__name', name || 'Jemand'));
|
||||
k.append(el('span', 'anruf__stand', lage === 'da' ? 'ist dabei' : 'klingelt …'));
|
||||
return k;
|
||||
}
|
||||
|
||||
/** Einen Schalter auf an/aus stellen.
|
||||
*
|
||||
* Die Aufschrift bleibt IMMER dieselbe (die Sache), der Zustand
|
||||
@@ -408,13 +484,30 @@
|
||||
}
|
||||
|
||||
async function starten(raumId, mitVideo, raumName) {
|
||||
/* WEN RUFE ICH AN? Der Chat weiss es und gibt es mit. Faellt
|
||||
der Name aus (aelterer Aufruf), bleibt es bei „Anruf" --
|
||||
das ist immer noch richtig, nur weniger. */
|
||||
wer(raumName || 'Anruf');
|
||||
if (anruf) return;
|
||||
kastenBauen();
|
||||
$('anruf').hidden = false;
|
||||
/* WEN RUFE ICH AN? Der Chat weiss es und gibt es mit. Faellt
|
||||
der Name aus (aelterer Aufruf), bleibt es bei „Anruf" --
|
||||
das ist immer noch richtig, nur weniger.
|
||||
|
||||
NACH `kastenBauen()`, UND DAS IST DER PUNKT (20.09.2026):
|
||||
Vorher stand diese Zeile DAVOR. Da gibt es das Element
|
||||
`#anruf-wer` noch gar nicht -- `wer()` fand nichts, tat nichts,
|
||||
und der Name war weg. Oben stand deshalb bei JEDEM ersten Anruf
|
||||
„Anruf" statt „Luna Sanchez", obwohl der Chat ihn korrekt
|
||||
mitgab. Der Kommentar daneben beschrieb die Absicht und nicht,
|
||||
was passierte -- ein Kommentar, der eine Absicht beschreibt,
|
||||
erfuellt sie nicht.
|
||||
|
||||
Gefunden hat es ein Bildschirmfoto, nicht das Lesen: Der Code
|
||||
liest sich richtig, und der Rueckfall „Anruf" ist plausibel
|
||||
genug, um nicht aufzufallen.
|
||||
|
||||
Der frueher hier stehende `if (anruf) return;` ist mit nach oben
|
||||
gewandert. Das ist auch sachlich besser: Laeuft schon ein
|
||||
Gespraech, soll ein zweiter Aufruf es nicht umbenennen. */
|
||||
wer(raumName || 'Anruf');
|
||||
/* JEDES GESPRAECH FAENGT LEISE AN (20.09.2026) -- an BEIDEN
|
||||
Wegen, Anrufen und Rangehen. Einer allein waere die
|
||||
Haelfte, und die andere Haelfte faellt niemandem auf,
|
||||
@@ -449,6 +542,10 @@
|
||||
$('anruf-video').hidden = !mitVideo;
|
||||
if (mitVideo) $('anruf-video').setAttribute('aria-pressed', 'true');
|
||||
lage('Es klingelt …');
|
||||
/* JETZT ZEICHNEN, nicht erst wenn jemand rangeht: Dies ist der
|
||||
Moment, in dem die Flaeche bisher leer war -- und ein leerer
|
||||
Kasten mit „Es klingelt ..." sieht aus wie einer, der haengt. */
|
||||
leuteZeichnen();
|
||||
/* DAS FREIZEICHEN. Ein stiller Kasten mit laufender Uhr sagt nur,
|
||||
dass etwas passiert -- nicht, was. */
|
||||
freiTon();
|
||||
@@ -528,6 +625,7 @@
|
||||
|
||||
/* Mit allen, die schon dabei sind, eine Verbindung aufbauen --
|
||||
aber das ANGEBOT macht nur, wer die kleinere Nummer hat. */
|
||||
namenMerken(d.wer);
|
||||
for (const p of d.wer || []) {
|
||||
if (p.id === ichId) continue;
|
||||
if (ichId < p.id) angebotMachen(p.id);
|
||||
@@ -580,20 +678,38 @@
|
||||
eigen.srcObject = anruf.eigener;
|
||||
ziel.append(eigen);
|
||||
}
|
||||
for (const [wer, strom] of anruf.stroeme) {
|
||||
for (const [werId, strom] of anruf.stroeme) {
|
||||
if (anruf.video) {
|
||||
const v = el('video', 'anruf__bild');
|
||||
v.autoplay = true; v.playsInline = true;
|
||||
v.srcObject = strom;
|
||||
ziel.append(v);
|
||||
} else {
|
||||
/* Der Ton muss abgespielt werden -- das Element bleibt, nur
|
||||
unsichtbar. Es traegt die Verbindung, nicht die Anzeige. */
|
||||
const t = el('audio');
|
||||
t.autoplay = true;
|
||||
t.srcObject = strom;
|
||||
ziel.append(t);
|
||||
ziel.append(el('span', 'anruf__name', 'Verbunden'));
|
||||
/* HIER STAND „Verbunden" -- einmal je Person, ohne Namen.
|
||||
Bei dreien dreimal dasselbe Wort, und man sah nicht, wer. */
|
||||
ziel.append(gesichtsfeld(anruf.namen?.get(werId), 'da'));
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- NOCH NIEMAND DRAN: zeigen, WEN man anruft ----------------
|
||||
Die Flaeche war in diesem Moment leer, und ein leerer Kasten mit
|
||||
„Es klingelt ..." sieht aus wie einer, der haengt -- ausgerechnet
|
||||
in der Sekunde, in der man am unsichersten ist. */
|
||||
if (!anruf.video && !anruf.stroeme.size) {
|
||||
const gegenueber = $('anruf-wer')?.textContent?.trim();
|
||||
/* „Anruf" ist der Rueckfalltext, kein Name -- dann lieber gar
|
||||
kein Gesicht als ein Kreis mit „A" darin. */
|
||||
if (gegenueber && gegenueber !== 'Anruf') {
|
||||
/* `true`: Name und Zustand stehen schon in der Kopfzeile --
|
||||
siehe die Begruendung in `gesichtsfeld`. */
|
||||
ziel.append(gesichtsfeld(gegenueber, 'wartet', true));
|
||||
}
|
||||
void wer;
|
||||
}
|
||||
/* Der Zustand gilt auch fuer die Elemente, die es gerade eben noch
|
||||
nicht gab -- und die Geraeteauswahl kann erst hier entstehen,
|
||||
@@ -975,6 +1091,7 @@
|
||||
if (!d.laeuft) { nachfrageStoppen(); tonAus(); lage('Der Anruf ist vorbei.');
|
||||
setTimeout(() => { if (anruf) auflegen(); }, 1500); return; }
|
||||
|
||||
namenMerken(d.wer);
|
||||
const andere = (d.wer || []).filter((w) => w.id !== ichId);
|
||||
if (!andere.length) return; /* es klingelt weiter, alles richtig */
|
||||
|
||||
@@ -1048,6 +1165,21 @@
|
||||
Den richtigen Zeitpunkt kennt nur die Verbindung selbst --
|
||||
`onconnectionstatechange` meldet ihn (siehe oben). */
|
||||
lage('Baut auf …');
|
||||
/* DEN NAMEN MITNEHMEN (20.09.2026).
|
||||
|
||||
Hier fehlte er, und das Loch war genau umgekehrt zu dem, was
|
||||
man erwartet: Wer ANGERUFEN wird, erfaehrt die Namen ueber
|
||||
`dazustossen` (die Antwort des Servers enthaelt alle). Wer
|
||||
ANRUFT, bekommt beim Start nur sich selbst -- alle weiteren
|
||||
kommen ausschliesslich ueber dieses Ereignis. Ohne diese Zeile
|
||||
stand bei ihm unter jedem Kreis „Jemand", und ausgerechnet der
|
||||
Anrufer sah als Einziger keine Namen.
|
||||
|
||||
Gefunden hat es die Pruefung, aber erst, nachdem sie
|
||||
verschaerft wurde: Der erste Anlauf verlangte nur „Name laenger
|
||||
als ein Zeichen" -- und „Jemand" ist sechs Zeichen lang. Eine
|
||||
Pruefung, die den Rueckfalltext durchlaesst, prueft nichts. */
|
||||
namenMerken([d.person]);
|
||||
/* Der Neue: Angebot macht, wer die kleinere Nummer hat. */
|
||||
if (ichId < d.person.id) angebotMachen(d.person.id);
|
||||
else verbindungFuer(d.person.id);
|
||||
|
||||
Reference in New Issue
Block a user