Am Handy stand nicht da, mit wem man schreibt

Gemessen in der Kopfzeile eines Gespraechs, Name "Team-Runde":

    360 px ->  0 px sichtbar (98 noetig)
    390 px -> 12 px
    412 px -> 33 px
   1280 px -> passt

Auf JEDEM Telefon stand also kein Name da -- man oeffnet ein Gespraech
und sieht nicht, mit wem. Und weil die Zeile nicht leer aussieht
(Zurueck-Pfeil, fuenf Knoepfe), wirkt sie nicht kaputt, sondern eng.

URSACHE: `flex: 1` heisst ausgeschrieben `1 1 0%` -- Grundbreite NULL.
Damit "passt" der Name rechnerisch immer, egal wie eng es ist, und es
bricht nie etwas um. Die Knopfreihe daneben hat `flex: none` und
schrumpft nie; seit die Knoepfe am Finger 44 px breit sind, bleibt bei
sechs Knoepfen nichts uebrig.

Zwei Stellen setzten dieselbe Eigenschaft, die spezifischere gewann --
die erste Reparatur wirkte deshalb nur bei 360 px und sonst nicht.
Beide nennen jetzt dieselbe Grundbreite.

KEINE NEUE SCHWELLE: `flex-wrap` bricht genau dann um, wenn der Platz
wirklich nicht reicht. Dieses Haus ist an festen Breiten schon zweimal
gescheitert (Kopfleiste, 06.09.2026); kommt morgen ein siebter Knopf
dazu, stimmt es weiter. Ergebnis: 244 / 268 / 289 px statt 0 / 12 / 33.

---- WARUM DER HANDY-RUNDGANG DAS NICHT GEFUNDEN HAT ----------------

Zwei eigene Entscheidungen, jede fuer sich vernuenftig, zusammen ein
Loch:

  1. `sichtbar()` verlangt `width > 0`. Ein auf null gequetschtes
     Element ist unsichtbar -- und "unsichtbar" hiess "nichts zu
     pruefen". Genau falsch herum: Nichts zu sehen IST der Befund.
  2. `text-overflow: ellipsis` gilt als Absicht. Das stimmt auch --
     ein langer Name soll gekuerzt werden. Es stimmt nur nicht mehr,
     wenn nichts uebrig bleibt.

Die neue Regel ist bewusst schmal: gemeldet wird nur, was unter 40 px
sichtbar ist und mindestens das Doppelte braeuchte. "Jede Kuerzung
melden" waeren die ~350 Fehlalarme, die diese Pruefung schon einmal
zugedeckt haben.

NACHGEMESSEN: 206 Seitenaufrufe, 91 638 Elemente. Die Regel schlaegt
an genau EINER Stelle an (kalender.html, sechsmal) und sonst nirgends
-- 64 -> 70 Befunde. Die Pruefung ist genauer geworden, nicht die App
schlechter.

DER KALENDER-FUND BLEIBT OFFEN: Im Monatsraster ist ein Tag am Handy
36 px breit, ein Eintrag braucht 186 bis 317. Das ist kein Versehen im
Code, sondern die Frage, ob die Monatsansicht am Telefon ueberhaupt
die richtige Vorgabe ist -- eine Entscheidung, keine Reparatur.

GEPRUEFT: pruef-chat-optik 39/0 (drei neu, mit einer Gegenprobe, die
den gemessenen Fall HERSTELLT -- fuenf Knoepfe wie in einer Gruppe;
der erste Anlauf blieb gruen, weil in einem Zweiergespraech nur drei
stehen und der Platz auch ohne Reparatur reicht: 12 px mit der alten
Angabe, 268 mit der neuen, im selben Aufbau).

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-20 18:14:08 +02:00
co-authored by Claude Opus 5
parent 2a26a49f91
commit 75019ec8c3
40 changed files with 689 additions and 509 deletions
+96
View File
@@ -493,6 +493,102 @@ melde("\n=== Der Fuss bleibt in der Blase ===");
await luna.seite.unroute("**/api/chat/raeume/*/nachrichten");
}
/* =======================================================================
MAN MUSS SEHEN, MIT WEM MAN SCHREIBT (20.09.2026)
Gemessen am Handy, Gespraech "Team-Runde":
360 px -> 0 px sichtbar (98 noetig)
390 px -> 12 px
412 px -> 33 px
Auf JEDEM Telefon stand also kein Name in der Kopfzeile. Man oeffnet
ein Gespraech und weiss nicht, mit wem -- und weil die Zeile nicht
leer aussieht (Zurueck-Pfeil, fuenf Knoepfe), wirkt sie nicht kaputt,
sondern nur eng.
WARUM DER GROSSE HANDY-RUNDGANG ES NICHT GEFUNDEN HAT -- zwei eigene
Entscheidungen, die zusammen ein Loch ergaben:
1. Er ueberspringt, was `width > 0` nicht erfuellt. Ein auf null
gequetschtes Element ist unsichtbar, und "unsichtbar" hiess
dort "nichts zu pruefen".
2. Er verzeiht `text-overflow: ellipsis` als ABSICHT. Das ist
richtig -- ein langer Name soll gekuerzt werden. Es ist nur
dann falsch, wenn gar nichts mehr uebrig ist.
Beides ist einzeln vernuenftig. Deshalb steht die Pruefung hier, wo
sie genau eine Sache misst, statt die Regeln dort aufzuweichen.
======================================================================= */
melde("\n=== Man sieht, mit wem man schreibt ===");
{
let gemessen = 0;
const zuEng = [];
for (const breite of [320, 360, 390, 430]) {
await luna.seite.setViewportSize({ width: breite, height: 844 });
await luna.seite.waitForTimeout(400);
const m = await luna.seite.evaluate(() => {
const t = document.getElementById("verlauf-titel");
if (!t) return null;
const r = t.getBoundingClientRect();
return { text: (t.textContent || "").trim(), sicht: Math.round(r.width),
noetig: Math.round(t.scrollWidth) };
});
if (!m || !m.text) continue;
gemessen++;
/* SICHTBAR MUSS SEIN, WAS GEBRAUCHT WIRD -- oder wenigstens so
viel, dass man den Namen erkennt. Ein Drittel eines Namens ist
kein Name. */
if (m.sicht < Math.min(m.noetig, 90)) {
zuEng.push(`${breite}px: ${m.sicht} von ${m.noetig} px`);
}
}
/* DIE ZAHL GEHOERT IN DIE BEDINGUNG: Faende die Schleife gar keinen
Titel, waere "nichts zu eng" trivialerweise wahr. */
ok(gemessen === 4 && zuEng.length === 0,
`der Gespraechsname ist auf allen ${gemessen} Breiten lesbar`
+ (zuEng.length ? " — ZU ENG: " + zuEng.join(", ") : ""));
/* ---- GEGENPROBE ------------------------------------------------
ERST DEN GEMESSENEN FALL NACHSTELLEN. Der erste Anlauf drehte nur
die Angabe zurueck und blieb gruen: In DIESEM Gespraech stehen
drei Knoepfe, da reicht der Platz auch ohne die Reparatur. Der
Fehler trat in einer GRUPPE auf, wo fuenf Knoepfe stehen --
Anrufen, Video, Aufloesen, Wegraeumen, Wer-ist-drin.
Eine Gegenprobe, die den Fall nicht herstellt, den sie pruefen
soll, ist keine. Deshalb bekommt die Knopfreihe hier die Breite,
die fuenf Knoepfe wirklich brauchen (5 x 44 + 4 x 6 Abstand).
Damit muss die alte Angabe den Namen zerdruecken -- und die neue
nicht. Beide Richtungen werden gemessen. */
await luna.seite.setViewportSize({ width: 390, height: 844 });
await luna.seite.waitForTimeout(300);
const ab = await luna.seite.evaluate(() => {
const eng = document.createElement("style");
eng.textContent = ".chat__kopf-knoepfe { min-width: 244px !important; }";
document.head.append(eng);
const t = document.getElementById("verlauf-titel");
const mitNeu = Math.round(t.getBoundingClientRect().width);
const alt = document.createElement("style");
alt.textContent = ".chat__kopf--verlauf .chat__kopf-text { flex: 1 1 0 !important; }";
document.head.append(alt);
const mitAlt = Math.round(t.getBoundingClientRect().width);
alt.remove(); eng.remove();
return { mitNeu, mitAlt };
});
ok(ab.mitAlt < 40,
`Gegenprobe: mit der alten Angabe bleiben ${ab.mitAlt} px — die Pruefung kann auch NEIN sagen`);
ok(ab.mitNeu >= 90,
` und mit der neuen ${ab.mitNeu} px, im selben Aufbau — die Reparatur ist der Unterschied`);
await luna.seite.setViewportSize({ width: 1280, height: 900 });
await luna.seite.waitForTimeout(300);
}
await luna.ctx.close();
await pat.ctx.close();
await browser.close();
+43 -1
View File
@@ -386,6 +386,45 @@ const messen = () => {
return e.scrollWidth > e.clientWidth + 3 || e.scrollHeight > e.clientHeight + 3;
}).slice(0, 4).map((e) => `${name(e)} „${(e.textContent || "").trim().slice(0, 28)}…"`);
/* ---- Auf fast nichts zusammengedrückter Text (20.09.2026) --------
ZWEI EIGENE ENTSCHEIDUNGEN ERGABEN ZUSAMMEN EIN LOCH, und es hat
einen echten Fehler durchgelassen: In der Kopfzeile eines
Gesprächs blieben vom Namen 0 bis 33 px übrig — auf JEDEM
Telefon. Man öffnete einen Chat und sah nicht, mit wem man
schreibt.
Warum hier nichts gemeldet wurde:
1. `sichtbar()` verlangt `width > 0`. Ein auf null gequetschtes
Element ist unsichtbar -- und "unsichtbar" hiess "nichts zu
prüfen". Genau falsch herum: Nichts zu sehen IST der Befund.
2. `text-overflow: ellipsis` gilt als Absicht. Das stimmt auch
-- ein langer Name soll gekürzt werden. Es stimmt nur nicht
mehr, wenn nichts übrig bleibt.
DIE REGEL IST BEWUSST SCHMAL. "Jede Kürzung melden" wären die
~350 Fehlalarme, die weiter oben schon einmal alles zugedeckt
haben. Gemeldet wird nur, was UNTER 40 px sichtbar ist und
mindestens das Doppelte bräuchte -- da steht kein Wort mehr,
sondern ein Buchstabe mit Punkten. */
const zerquetscht = alle.filter((e) => {
if (e.children.length > 0) return false;
if (nurVorlesen(e)) return false;
const t = (e.textContent || "").trim();
if (t.length < 4) return false;
const st = getComputedStyle(e);
if (st.visibility === "hidden" || st.display === "none") return false;
if (Number(st.opacity) <= 0.05) return false;
/* Steht es überhaupt im Aufbau? Ein Element in einem geschlossenen
Klappfeld ist kein Fall -- es ist gar nicht dran. */
if (!e.offsetParent && st.position !== "fixed") return false;
const breiteHier = e.getBoundingClientRect().width;
const noetig = e.scrollWidth;
return breiteHier < 40 && noetig >= breiteHier * 2 && noetig > 60;
}).slice(0, 4).map((e) => `${name(e)} „${(e.textContent || "").trim().slice(0, 24)}…" `
+ `${Math.round(e.getBoundingClientRect().width)} statt ${Math.round(e.scrollWidth)}px`);
/* ---- Zu kleine Tippziele ----------------------------------------- */
const klein = bedienbar.filter((e) => {
const r = e.getBoundingClientRect();
@@ -459,7 +498,7 @@ const messen = () => {
elemente: alle.length,
bedienbar: bedienbar.length,
ueber: document.documentElement.scrollWidth - document.documentElement.clientWidth,
ueberstand, abgeschnitten, klein, ueberdeckt, namenlos,
ueberstand, abgeschnitten, zerquetscht, klein, ueberdeckt, namenlos,
};
};
@@ -595,6 +634,9 @@ for (const [breite, hoehe, geraet] of BREITEN) {
details.push(`${kurz}: ragt über den Rand — ${m.ueberstand.join(", ")}`);
schlecht++;
}
if (m.zerquetscht?.length) {
details.push(`${kurz}: Text auf fast nichts gedrückt — ${m.zerquetscht.join(", ")}`); schlecht++;
}
if (m.abgeschnitten.length) {
details.push(`${kurz}: Text abgeschnitten — ${m.abgeschnitten.join(", ")}`); schlecht++;
}