Ein Anruf faengt leise an

Filipe: "uebrigens soll man auswaehlen koennen ob man lautsprecher will
oder nicht bitte. es soll ohne lautsprecher anfangen das gespraech und
nur wenn man drauf klickt soll es laut werden ... es soll nicht
raushaengen oder so, das ist nicht cool."

DER GRUND IST DER STREAM. Ein Anruf, der beim Annehmen sofort aus den
Lautsprechern kommt, ist im schlimmsten Fall fuer alle Zuschauer zu
hoeren, bevor irgendjemand reagieren kann. Das laesst sich nicht
zurueckholen.

HIER STAND `hoeren = true` mit der Begruendung: "Wer den Ton abgestellt
hat, will ihn nicht beim naechsten Gespraech wieder an." Das war richtig
gedacht und ist jetzt umgedreht -- aus demselben Grund, nur in die
andere Richtung: Der Zustand soll NICHT ueberdauern. Eine Entscheidung
von vorhin darf nicht fuer ein Gespraech gelten, von dem man noch
nichts wusste. Zurueckgesetzt wird an BEIDEN Wegen, beim Anrufen und
beim Rangehen -- einer allein waere die Haelfte, und die andere Haelfte
faellt niemandem auf, bis es einmal zu laut war.

UND MAN SIEHT ES. Leise anfangen ohne Hinweis waere die naechste
Sackgasse: "ich hoere nichts" ohne Grund und ohne Weg. Ein Balken sagt
es, solange es gilt, und verschwindet in dem Moment, in dem man den Ton
anmacht. Er ist SELBST der Knopf -- wer liest "tippen, um den Ton
anzumachen", will genau das tun. Gedaempftes Bernstein statt Alarmrot:
Es ist kein Fehler, sondern ein Zustand.

DABEI EINEN EIGENEN FEHLER GEFANGEN: Der Balken fragte `!anruf` -- und
diese Variable wird erst gesetzt, NACHDEM der Kasten aufgeht. Beim
Aufbauen blieb er deshalb versteckt, und man sass in einem stummen
Gespraech ohne einen Satz dazu. Genau der Zustand, den er verhindern
soll. Jetzt haengt er am sichtbaren Kasten.

DIE PRUEFUNG WURDE ROT und hat damit ihre Arbeit getan -- sie hielt das
alte Verhalten fest. Umgedreht, nicht gestrichen: Die wichtigste Falle
(ueberlebt der Schalter das Neuzeichnen, wenn jemand auflegt?) bleibt,
nur der erwartete Zustand hat sich gedreht.

GEPRUEFT: pruef-anruf 117/0 (war 114) -- drei Aussagen mehr, darunter
dass der Hinweis da ist, 44 px hoch und im richtigen Moment
verschwindet.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-20 19:01:28 +02:00
co-authored by Claude Opus 5
parent 01151574ae
commit c59517cb23
40 changed files with 699 additions and 527 deletions
+53
View File
@@ -2155,3 +2155,56 @@
.chat-raum__erwaehnt { border: 1px solid CanvasText; }
.erwaehn-liste__eintrag[data-wahl="ja"] { border: 2px solid Highlight; }
}
/* ---- „Du hörst noch nichts" (20.09.2026) ----------------------------
Filipe: „es soll ohne lautsprecher anfangen das gespräch und nur wenn
man drauf klickt soll es laut werden."
Wörtlich umgesetzt — und deshalb braucht es diesen Balken. Ein
Gespräch, in dem man nichts hört und nicht weiß warum, ist die
nächste Sackgasse. Er steht zwischen Kopfzeile und Gesprächsteilnehmern,
also genau dort, wohin man zuerst schaut.
GEDÄMPFT, NICHT ALARMROT. Es ist kein Fehler, sondern ein Zustand,
den man selbst gewählt bekommt — und Alarmfarben für Normalzustände
sind der schnellste Weg, dass man Alarmfarben nicht mehr ernst
nimmt. Ein ruhiges Bernstein sagt „da ist etwas", ohne zu schreien. */
.anruf__stumm {
appearance: none;
display: flex; align-items: center; gap: 10px;
width: 100%; min-height: 44px;
margin: 0 0 10px;
padding: 9px 12px;
border: 1px solid color-mix(in srgb, #f0b429 42%, transparent);
border-radius: var(--radius-klein);
background: color-mix(in srgb, #f0b429 12%, transparent);
color: var(--text);
font: inherit; font-size: .88rem; font-weight: 600;
text-align: left; cursor: pointer;
transition: background var(--tempo), border-color var(--tempo);
}
.anruf__stumm:hover {
background: color-mix(in srgb, #f0b429 20%, transparent);
border-color: color-mix(in srgb, #f0b429 62%, transparent);
}
.anruf__stumm:focus-visible { outline: 2px solid var(--akzent); outline-offset: 2px; }
.anruf__stumm svg {
flex: none; width: 20px; height: 20px;
fill: none; stroke: #f0b429; stroke-width: 1.7;
stroke-linecap: round; stroke-linejoin: round;
}
/* Ein ruhiges Pulsieren, damit er im Augenwinkel auffällt -- und
nichts davon für jemanden, der weniger Bewegung eingestellt hat.
Das ist keine Deko: Wer den Balken übersieht, hört sein Gespräch
nicht. */
@media (prefers-reduced-motion: no-preference) {
.anruf__stumm { animation: stumm-atmen 2.6s ease-in-out infinite; }
@keyframes stumm-atmen {
0%, 100% { border-color: color-mix(in srgb, #f0b429 42%, transparent); }
50% { border-color: color-mix(in srgb, #f0b429 78%, transparent); }
}
}
@media (forced-colors: active) {
.anruf__stumm { border: 2px solid CanvasText; animation: none; }
}
+89 -4
View File
@@ -146,6 +146,25 @@
</span>
<span class="anruf__zeit" id="anruf-zeit"></span>
</div>
<!-- TON AUS IST EIN ZUSTAND, DEN MAN SEHEN MUSS (20.09.2026).
Filipe: „es soll ohne lautsprecher anfangen das gespraech und
nur wenn man drauf klickt soll es laut werden."
Wortwoertlich umgesetzt -- aber ein Gespraech, in dem man
nichts hoert und nicht weiss warum, ist die naechste
Sackgasse. Deshalb steht es gross da, solange es gilt, und
verschwindet in dem Moment, in dem man den Ton anmacht.
Der Balken ist ANTIPPBAR: Wer den Satz liest, will genau das
tun, was dort steht -- ihn dann erst den passenden Knopf
suchen zu lassen, waere ein unnoetiger Schritt. -->
<button type="button" class="anruf__stumm" id="anruf-stumm" hidden>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M4 9.5h3.5L12 5.5v13L7.5 14.5H4z"/>
<path d="M4 4l16 16"/>
</svg>
<span>Du hörst noch nichts — tippen, um den Ton anzumachen</span>
</button>
<div class="anruf__leute" id="anruf-leute"></div>
<div class="anruf__knoepfe">
<button type="button" class="anruf__schalter" id="anruf-ton" aria-pressed="true">
@@ -156,7 +175,7 @@
</svg>
<span class="anruf__schalter-text">Mikro</span>
</button>
<button type="button" class="anruf__schalter" id="anruf-hoeren" aria-pressed="true">
<button type="button" class="anruf__schalter" id="anruf-hoeren" aria-pressed="false">
<svg class="anruf__zeichen" viewBox="0 0 24 24" aria-hidden="true">
<path d="M4 9.5h3.5L12 5.5v13L7.5 14.5H4z"/>
<path d="M16 9a4.5 4.5 0 0 1 0 6M18.5 6.5a8 8 0 0 1 0 11"/>
@@ -215,6 +234,10 @@
});
$('anruf-ton').addEventListener('click', tonSchalten);
$('anruf-hoeren').addEventListener('click', hoerenSchalten);
/* DER HINWEISBALKEN IST SELBST DER KNOPF. Wer liest „tippen, um
den Ton anzumachen", will genau das tun -- ihn danach noch den
richtigen Schalter suchen zu lassen, waere ein Schritt zu viel. */
$('anruf-stumm')?.addEventListener('click', hoerenSchalten);
$('anruf-video').addEventListener('click', videoSchalten);
$('anruf-auflegen').addEventListener('click', () => auflegen(true));
return k;
@@ -392,6 +415,11 @@
if (anruf) return;
kastenBauen();
$('anruf').hidden = false;
/* 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,
bis es einmal zu laut war. */
tonZuruecksetzen();
lage('Mikrofon …');
/* Läuft NEBEN der Mikrofonfrage, nicht davor: Das Auffrischen
kostet sonst Zeit, in der nichts passiert -- und die Frage nach
@@ -471,6 +499,11 @@
await adressenFertig;
kastenBauen();
$('anruf').hidden = false;
/* 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,
bis es einmal zu laut war. */
tonZuruecksetzen();
let eigener;
try {
eigener = await eigenenStromHolen(d.video);
@@ -516,6 +549,9 @@
for (const v of anruf.verbindungen.values()) { try { v.close(); } catch { /* egal */ } }
for (const s of anruf.eigener.getTracks()) s.stop();
anruf = null;
/* Der Hinweis gehoert zum laufenden Gespraech. Bleibt er stehen,
sagt er etwas ueber ein Gespraech, das es nicht mehr gibt. */
stummBalkenZeigen();
/* Was noch wartet, gehoert zu einem Gespraech, das es nicht mehr
gibt. Bliebe es liegen, waere es beim naechsten Anruf das erste,
was verarbeitet wird -- mit einer Beschreibung, die zu niemandem
@@ -615,10 +651,27 @@
Wo es GEHT (Rechner mit Chrome, Edge oder Safari), steht dafuer
eine echte Geraeteauswahl daneben -- und nur dort. */
/** Hoeren wir die anderen? Steht ausserhalb von `anruf`: Wer den Ton
/** Hoeren wir die anderen?
*
* STARTET AUS, UND ZWAR BEI JEDEM ANRUF (20.09.2026).
*
* Filipe: „es soll ohne lautsprecher anfangen das gespraech und nur
* wenn man drauf klickt soll es laut werden ... es soll nicht
* raushaengen oder so, das ist nicht cool."
*
* Der Grund ist der Stream: Ein Anruf, der beim Annehmen sofort aus
* den Lautsprechern kommt, ist im schlimmsten Fall fuer alle
* Zuschauer zu hoeren, bevor irgendjemand reagieren kann. Das laesst
* sich nicht zurueckholen.
*
* HIER STAND FRUEHER `true` mit der Begruendung: „Wer den Ton
* abgestellt hat, will ihn nicht beim naechsten Gespraech wieder
* an. */
let hoeren = true;
* an." Das war richtig gedacht und ist jetzt umgedreht -- aus
* demselben Grund, nur in die andere Richtung: Der Zustand soll
* NICHT ueberdauern, sondern jedes Gespraech faengt leise an. Eine
* Entscheidung, die man einmal getroffen hat, darf nicht fuer ein
* Gespraech gelten, von dem man noch nichts wusste. */
let hoeren = false;
/** Auf welches Geraet der Ton geht. Leer = das des Systems. */
let ausgabe = '';
@@ -647,6 +700,38 @@
hoeren = !hoeren;
schalterSetzen($('anruf-hoeren'), hoeren, 'Ton der anderen');
hoerenAnwenden();
stummBalkenZeigen();
}
/** Den Hinweis "du hoerst noch nichts" ein- oder ausblenden.
*
* An EINER Stelle, damit er nicht an dreien vergessen wird: beim
* Anfangen, beim Umschalten und beim Auflegen. */
function stummBalkenZeigen() {
const b = $('anruf-stumm');
if (!b) return;
/* AM SICHTBAREN KASTEN, NICHT AN `anruf` (berichtigt 20.09.2026).
Der erste Anlauf fragte `!anruf` -- und die Variable wird erst
gesetzt, NACHDEM der Kasten aufgeht. Beim Aufbauen war sie also
noch leer, der Hinweis blieb versteckt, und man sass in einem
stummen Gespraech ohne einen Satz dazu. Genau der Zustand, den
er verhindern soll.
Der Kasten selbst ist die ehrlichere Frage: Ist er zu, gibt es
nichts zu hoeren; ist er auf, gilt der Hinweis. */
b.hidden = hoeren || $('anruf')?.hidden !== false;
}
/** Jedes Gespraech faengt leise an -- siehe die Begruendung bei
* `hoeren`. Wird beim Aufbauen eines Anrufs gerufen, nicht beim
* Laden der Seite: Sonst gaelte die Entscheidung von vorhin
* weiter. */
function tonZuruecksetzen() {
hoeren = false;
schalterSetzen($('anruf-hoeren'), false, 'Ton der anderen');
hoerenAnwenden();
stummBalkenZeigen();
}
/** Baut die Geraeteauswahl -- oder eben nicht.