From af61f77e9297ba8a1f5654120bc1668dbffb2597 Mon Sep 17 00:00:00 2001 From: Dogfather Date: Tue, 29 Sep 2026 14:23:57 +0200 Subject: [PATCH] Die Transportknoepfe sind am Daumen wieder 44 Pixel hoch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DER BEFUND pruef-handy-teamdogi meldete auf iPhone UND Android, bei zwei Rollen, denselben Mangel: reaktion.html: zu kleine Tippziele -- button#v-zurueck 48x40, button#v-vor 48x40, button#v-naechstes 83x40 Die Grundregel von `.spur__knopf` steht auf `min-height: 40px`. Am Rechner ist das richtig; am Finger sind es vier Pixel zu wenig, und eine Ausnahme dafuer gab es nicht. WARUM DAS ERST HEUTE AUFFAELLT Die Transportleiste war am Handy bis gestern gar nicht erreichbar -- sie lag 162 Pixel unter dem Fensterrand, und der Koerper hat `overflow: hidden`. Was nicht sichtbar ist, wird nicht gemessen. Die Reparatur von gestern hat den Mangel also nicht verursacht, sondern aufgedeckt. Gemessen nach der Aenderung: Transportleiste 207 statt 203 Pixel, Saal 775 = Leiste 101 + Kino 467 + Regie 336. Kein Knopf liegt ueber einem anderen, die Leiste verdeckt kein Bedienelement der Regie. DIE FINGERWACHE ZAEHLT JETZT FENSTER, NICHT DATEIEN Die erste Fassung fragte: "Steht `hasTouch` irgendwo in der Datei?" pruef-kalender allein hat sieben Fenster, davon drei schmale -- ein einziges `hasTouch` haette alle drei freigesprochen. Genau diese Mischung ist im Haus die Regel. Die geschaerfte Fassung fand prompt zwei Dateien, welche die grobe freigesprochen hatte. Beim Nachmessen: - pruef-chat-optik: FEHLALARM. Ihr `setViewportSize` sitzt auf einer Seite, deren Kontext `hasTouch: breite < 900` traegt -- wer danach nur die Groesse aendert, behaelt den Finger. Die Wache zaehlt solche Stellen jetzt nur noch, wenn in der ganzen Datei kein einziges `hasTouch` steht. Wo ich raten muesste, zaehle ich nicht: Eine Wache, die im Zweifel meldet, wird weggeklickt. - pruef-handy-teamdogi: ECHTER FUND. Ihr zweiter Kontext hatte keinen Finger, der erste schon. Repariert. Grundlinie damit von 23 auf 17. Neun Gegenproben statt sechs, darunter beide neuen Faelle. Drei Anlaeufe, drei Zahlen: grep 18, Wache je Datei 16, Wache je Fenster 17 (nach Abzug des Fehlalarms). Die erste Zahl, die eine Wache liefert, ist selten die richtige. NOCH OFFEN AUS DEMSELBEN LAUF notizen.html, nur auf 412 px: `a.zurueck` „Team Dogi…" ist 0 Pixel breit statt 82. Noch nicht angesehen. GEPRUEFT pruef-reaktion, -tippziele, -css-klassen: alle EXIT 0 pruef-fingermass 3 / 0 mess-reaktion EXIT 0, kein ACHTUNG, kein offener Punkt --- server/pruef-fingermass.mjs | 149 +++++++++++++++++++++--------- server/pruef-handy-teamdogi.mjs | 7 +- workspace/anruf-probe.html | 10 +- workspace/app.webmanifest | 8 +- workspace/assets/css/reaktion.css | 17 ++++ workspace/aufgaben.html | 38 ++++---- workspace/automation.html | 32 +++---- workspace/befinden.html | 34 +++---- workspace/bereich.html | 44 ++++----- workspace/bewerben.html | 38 ++++---- workspace/bewerbungen.html | 36 ++++---- workspace/buehne.html | 2 +- workspace/calls.html | 34 +++---- workspace/chat.html | 40 ++++---- workspace/content.html | 34 +++---- workspace/crew-index.html | 12 +-- workspace/crew.webmanifest | 8 +- workspace/dateien.html | 34 +++---- workspace/entwicklung.html | 36 ++++---- workspace/hilfe.html | 30 +++--- workspace/index.html | 10 +- workspace/kalender.html | 34 +++---- workspace/leistung.html | 32 +++---- workspace/material.html | 32 +++---- workspace/notizen.html | 28 +++--- workspace/personen.html | 32 +++---- workspace/profil.html | 36 ++++---- workspace/reaktion.html | 34 +++---- workspace/rechte.html | 34 +++---- workspace/report.html | 36 ++++---- workspace/scouting.html | 32 +++---- workspace/start.html | 32 +++---- workspace/startcheck.html | 34 +++---- workspace/steckbrief.html | 36 ++++---- workspace/support.html | 28 +++--- workspace/tafel.html | 6 +- workspace/talente.html | 36 ++++---- workspace/team.html | 32 +++---- workspace/teamlage.html | 34 +++---- workspace/teilen.html | 30 +++--- workspace/treff-moderation.html | 32 +++---- workspace/treff-regeln.html | 32 +++---- workspace/uebersicht.html | 32 +++---- workspace/unsere-seiten.html | 30 +++--- workspace/unterstuetzen.html | 32 +++---- workspace/werdegang.html | 32 +++---- workspace/willkommen.html | 30 +++--- workspace/wissen.html | 34 +++---- 48 files changed, 795 insertions(+), 710 deletions(-) diff --git a/server/pruef-fingermass.mjs b/server/pruef-fingermass.mjs index 223420b6..a9330c44 100644 --- a/server/pruef-fingermass.mjs +++ b/server/pruef-fingermass.mjs @@ -46,38 +46,79 @@ const ORDNER = new URL(".", import.meta.url).pathname.replace(/^\/([A-Za-z]:)/, werden. Wird sie kleiner, gehoert sie hier angepasst — die Pruefung sagt es dann selbst. - EIN GREP HATTE 18 GEZAEHLT. Zwei davon waren Zahlen in - Kommentaren („gemessen bei 412 px"), keine Fenster. Deshalb liest - diese Pruefung nur die Stelle, die ein Fenster AUFMACHT, und - blendet Kommentare vorher aus. Die erste Zahl, die eine Wache - liefert, ist selten die richtige — auch hier war die genauere - Lesart um zwei kleiner. */ -const GRUNDLINIE = 16; + DREI ANLAEUFE, DREI ZAHLEN. Ein grep ueber die Dateien fand 18; + zwei davon waren Zahlen in Kommentaren („gemessen bei 412 px"), + keine Fenster. Die erste Fassung dieser Wache zaehlte dann DATEIEN + und kam auf 16 — aber `pruef-kalender.mjs` allein hat sieben + Fenster, davon drei schmale, und ein einziges `hasTouch` irgendwo + in der Datei haette alle drei freigesprochen. Gezaehlt wird + deshalb je FENSTER. + + Die geschaerfte Fassung fand dann prompt zwei Dateien, welche die + grobe freigesprochen hatte — `pruef-chat-optik` und + `pruef-handy-teamdogi`, beide mit EINEM Finger und einem blinden + Fenster daneben. Beim Nachmessen war die erste ein Fehlalarm (ihr + `setViewportSize` sitzt auf einer Seite, die den Finger schon + hat), die zweite ein echter Fund und sofort repariert. + + Die erste Zahl, die eine Wache liefert, ist selten die richtige. */ +const GRUNDLINIE = 17; /* Ab wann ist ein Fenster ein Telefon? 860 ist die Grenze, die im Haus schon in mess-reaktion und mess-chat-optik steht. Darueber hat ein Geraet mit hoher Wahrscheinlichkeit einen Zeiger. */ -const SCHMAL = /(?:width|breite)\s*[:=]\s*(\d{3})\b/g; +const SCHMAL = 860; const MISST = /getBoundingClientRect|offsetWidth|offsetHeight|clientWidth|clientHeight|scrollWidth|scrollHeight|boundingBox/; +const ohneKommentare = (text) => text + .replace(/\/\*[\s\S]*?\*\//g, " ") + .replace(/^\s*\/\/.*$/gm, " "); + /* NUR DIE STELLE, DIE EIN FENSTER AUFMACHT — nicht jede Zahl im Text. `width: 412` in einem Kommentar ueber eine Messung von - gestern ist keine Messung. */ -const fensterBreiten = (text) => { + gestern ist keine Messung. + + UND JE FENSTER, NICHT JE DATEI. Eine Wache, die eine Datei als + Ganzes abhakt, uebersieht genau die Mischung, die im Haus die + Regel ist: ein Fenster mit Finger, drei ohne. */ +export const fensterStellen = (text) => { const raus = []; - const ohneKommentar = text.replace(/\/\*[\s\S]*?\*\//g, " ").replace(/^\s*\/\/.*$/gm, " "); - for (const m of ohneKommentar.matchAll(/(?:newContext|setViewportSize|viewport)\s*[({][^)}]{0,200}/g)) { - for (const z of m[0].matchAll(SCHMAL)) raus.push(Number(z[1])); + const rein = ohneKommentare(text); + for (const m of rein.matchAll(/newContext\s*\(\s*\{[\s\S]{0,400}?\}\s*\)/g)) { + const br = [...m[0].matchAll(/width\s*:\s*(\d{3,4})\b/g)].map((z) => Number(z[1])); + if (!br.length) continue; + raus.push({ schmal: br.some((x) => x <= SCHMAL), finger: /hasTouch/.test(m[0]) }); + } + /* `setViewportSize` KANN `hasTouch` nicht nachtragen — es gehoert + zum Kontext und ist beim Anlegen entschieden. + + ABER ES KANN IHN AUCH NICHT WEGNEHMEN. Die erste Fassung zaehlte + jede solche Stelle als blind und meldete daraufhin + `pruef-chat-optik.mjs` — zu Unrecht: Deren Kontext traegt + `hasTouch: breite < 900`, und wer danach nur die Groesse + aendert, behaelt den Finger. Ein Fehlalarm, gefunden beim + Nachmessen des ersten Laufs. + + Gezaehlt wird die Stelle deshalb nur, wenn in der ganzen Datei + KEIN einziges `hasTouch` steht — dann stammt die Seite sicher + aus einem fingerlosen Kontext. Wo ich raten muesste, zaehle ich + nicht: Eine Wache, die im Zweifel meldet, wird weggeklickt. */ + if (!/hasTouch/.test(rein)) { + for (const m of rein.matchAll(/setViewportSize\s*\(\s*\{[^}]{0,150}\}/g)) { + const br = [...m[0].matchAll(/width\s*:\s*(\d{3,4})\b/g)].map((z) => Number(z[1])); + if (!br.length) continue; + raus.push({ schmal: br.some((x) => x <= SCHMAL), finger: false }); + } } return raus; }; -export const fingerlos = (text) => { - const breiten = fensterBreiten(text); - if (!breiten.some((b) => b <= 860)) return false; - if (/hasTouch/.test(text)) return false; - return MISST.test(text); -}; +/* Ein Fenster ist nur dann ein Befund, wenn die Datei ueberhaupt + MISST. Wer bei 390 px nachsieht, ob ein Text dasteht, braucht + keinen Finger. */ +export const blindeStellen = (text) => (MISST.test(text) + ? fensterStellen(text).filter((f) => f.schmal && !f.finger).length : 0); +export const fingerlos = (text) => blindeStellen(text) > 0; console.log("\n=== 1. Wer misst am Telefon ohne Finger? ==="); const dateien = readdirSync(ORDNER) @@ -92,56 +133,78 @@ if (dateien.length < 50) { } const funde = []; -let mitFinger = 0, amTelefon = 0; +let blind = 0, mitFinger = 0, amTelefon = 0; for (const name of dateien) { const text = readFileSync(join(ORDNER, name), "utf8"); - const breiten = fensterBreiten(text); - if (!breiten.some((b) => b <= 860)) continue; + const schmale = fensterStellen(text).filter((f) => f.schmal); + if (!schmale.length) continue; amTelefon++; - if (/hasTouch/.test(text)) { mitFinger++; continue; } - if (MISST.test(text)) funde.push(name); + mitFinger += schmale.filter((f) => f.finger).length; + const b = blindeStellen(text); + if (b) { blind += b; funde.push(`${name} (${b})`); } } -console.log(` ${amTelefon} Dateien oeffnen ein Telefonformat, ${mitFinger} davon mit Finger.`); -if (funde.length) console.log(" ohne Finger und mit Massband: " + funde.join(", ")); +console.log(` ${amTelefon} Dateien oeffnen ein Telefonformat, ` + + `${mitFinger} dieser Fenster haben einen Finger.`); +if (funde.length) console.log(" blinde Fenster mit Massband: " + funde.join(", ")); ok(amTelefon > 20, `${amTelefon} Dateien messen am Telefon — die Suche findet ueberhaupt etwas`); -if (funde.length > GRUNDLINIE) { - ok(false, `${funde.length} Messungen ohne Finger — das sind ${funde.length - GRUNDLINIE} MEHR ` - + `als die Grundlinie ${GRUNDLINIE}. Neu dazugekommen ist eine Messung, die auf ` - + "412 px eine Seite vermisst, die es auf keinem Telefon gibt. `hasTouch: true` " - + "gehoert in den newContext-Aufruf — setViewportSize kann es nicht nachtragen."); -} else if (funde.length < GRUNDLINIE) { - ok(false, `Nur noch ${funde.length} Messungen ohne Finger — die Grundlinie steht auf ` - + `${GRUNDLINIE}. Bitte in pruef-fingermass.mjs auf ${funde.length} senken, sonst deckt ` - + "sie Platz fuer die naechste."); +if (blind > GRUNDLINIE) { + ok(false, `${blind} blinde Fenster — das sind ${blind - GRUNDLINIE} MEHR als die ` + + `Grundlinie ${GRUNDLINIE}. Neu dazugekommen ist eine Messung, die auf einem ` + + "Telefonformat eine Seite vermisst, die es auf keinem Telefon gibt. " + + "`hasTouch: true` gehoert in den newContext-Aufruf — setViewportSize kann es " + + "nicht nachtragen."); +} else if (blind < GRUNDLINIE) { + ok(false, `Nur noch ${blind} blinde Fenster — die Grundlinie steht auf ${GRUNDLINIE}. ` + + `Bitte in pruef-fingermass.mjs auf ${blind} senken, sonst deckt sie Platz fuer ` + + "die naechste."); } else { - ok(true, `${funde.length} Messungen ohne Finger — unveraendert zur Grundlinie ${GRUNDLINIE}`); + ok(true, `${blind} blinde Fenster mit Massband — unveraendert zur Grundlinie ${GRUNDLINIE}`); } console.log("\n=== 2. Gegenprobe: kann sie auch NICHT IN ORDNUNG sagen? ==="); const faelle = [ ["der Fall vom 29.09. (schmal, misst, kein Finger)", 'const s = await b.newContext({ viewport: { width: 412, height: 900 } });\n' - + 'el.getBoundingClientRect()', true], + + 'el.getBoundingClientRect()', 1], ["mit Finger", 'const s = await b.newContext({ viewport: { width: 412, height: 900 }, hasTouch: true });\n' - + 'el.getBoundingClientRect()', false], + + 'el.getBoundingClientRect()', 0], ["nur ein Laptopfenster", 'const s = await b.newContext({ viewport: { width: 1280, height: 900 } });\n' - + 'el.getBoundingClientRect()', false], + + 'el.getBoundingClientRect()', 0], ["schmal, misst aber nichts", 'const s = await b.newContext({ viewport: { width: 390, height: 844 } });\n' - + 'await p.textContent("h1")', false], + + 'await p.textContent("h1")', 0], ["eine Breite, die nur im Kommentar steht", '/* gemessen bei width: 412 -- drei Zeilen */\n' + 'const s = await b.newContext({ viewport: { width: 1440, height: 900 } });\n' - + 'el.getBoundingClientRect()', false], + + 'el.getBoundingClientRect()', 0], ["setViewportSize statt newContext — kann hasTouch gar nicht setzen", - 'await p.setViewportSize({ width: 390, height: 844 });\nel.offsetWidth', true], + 'await p.setViewportSize({ width: 390, height: 844 });\nel.offsetWidth', 1], + /* DER FEHLALARM AUS DEM ERSTEN LAUF: Wer einen Finger-Kontext + anlegt und danach nur die Groesse aendert, behaelt den Finger. */ + ["Groesse aendern an einer Seite, die schon einen Finger hat", + 'const c = await b.newContext({ viewport: { width: 900, height: 900 },\n' + + ' hasTouch: breite < 900 });\n' + + 'await p.setViewportSize({ width: 390, height: 844 });\nel.offsetWidth', 0], + /* DER FALL, AN DEM DIE ERSTE FASSUNG SCHEITERTE: Ein Finger in der + Datei, drei blinde Fenster daneben. Sie sprach die ganze Datei + frei. */ + ["ein Finger spricht nicht die ganze Datei frei", + 'const a = await b.newContext({ viewport: { width: 390, height: 844 }, hasTouch: true });\n' + + 'const c = await b.newContext({ viewport: { width: 412, height: 900 } });\n' + + 'el.getBoundingClientRect()', 1], + ["zwei blinde Fenster sind zwei Befunde, nicht einer", + 'const a = await b.newContext({ viewport: { width: 390, height: 844 } });\n' + + 'const c = await b.newContext({ viewport: { width: 412, height: 900 } });\n' + + 'el.getBoundingClientRect()', 2], ]; -const daneben = faelle.filter(([, text, soll]) => fingerlos(text) !== soll).map(([n]) => n); +const daneben = faelle + .filter(([, text, soll]) => blindeStellen(text) !== soll) + .map(([n, text, soll]) => `${n} (${blindeStellen(text)} statt ${soll})`); ok(daneben.length === 0, daneben.length ? `Gegenprobe daneben bei: ${daneben.join(", ")}` : `Gegenprobe: alle ${faelle.length} Faelle richtig eingeordnet`); diff --git a/server/pruef-handy-teamdogi.mjs b/server/pruef-handy-teamdogi.mjs index c5a77c12..229a97c6 100644 --- a/server/pruef-handy-teamdogi.mjs +++ b/server/pruef-handy-teamdogi.mjs @@ -731,7 +731,12 @@ for (const [breite, hoehe, geraet] of BREITEN) { ===================================================================== */ melde("\n --- Gegenprobe (beide Fehler MÜSSEN gefunden werden) ---"); { - const kontext = await browser.newContext({ viewport: { width: 390, height: 844 }, ignoreHTTPSErrors: true }); + /* MIT FINGER (29.09.2026). Der zweite Kontext dieser Datei hatte + keinen -- der erste schon. Ohne `hasTouch` meldet der Browser + `pointer: fine`, und keine Regel aus `@media (pointer: coarse)` + greift; dort stehen die 44-Pixel-Beruehrziele. */ + const kontext = await browser.newContext({ viewport: { width: 390, height: 844 }, + hasTouch: true, isMobile: true, ignoreHTTPSErrors: true }); const seite = await kontext.newPage(); await seite.goto(BASIS + "/workspace/", { waitUntil: "load" }); await seite.waitForTimeout(600); diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 496474f0..6a604ee4 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,8 +16,8 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +