Chat: das Buehnenbild scheint durch, jeder Account bekommt seine Kachel
Hinter jeder Seite steht ohnehin eine Buehne (neun Szenen, fuer den
Chat die Lounge). Sie lag bisher hinter einer deckenden Flaeche --
vorhanden, geladen, unsichtbar. Sie durchscheinen zu lassen kostet
keine einzige Datei mehr, und auf der Adresse von Team Dogi kommt
damit von selbst deren eigene Fassung.
Das geht aber NUR, wenn der Text auf einer deckenden Kachel steht.
Sonst liegt Schrift auf einem Foto: an der dunklen Stelle lesbar, an
der hellen nicht, und beim Scrollen wechselt es. Filipes zweiter Satz
("die texte sollen immer in einer kachel sein") ist deshalb kein
Zusatzwunsch, sondern die Bedingung fuer den ersten.
Und jeder Account waehlt seinen Ton. Zwoelf Stueck, alle gleich
dunkel und gleich gesaettigt -- sie unterscheiden sich im Farbton und
in sonst nichts. Ein freier Farbwaehler klingt grosszuegiger und ist
die schlechtere Loesung: Mit ihm laesst sich Schwarz auf Schwarz
einstellen oder Neongelb, das allen anderen in die Augen sticht. Die
Kachel gehoert einem selbst, GESEHEN wird sie von allen anderen.
Gemessen: der schlechteste Kontrast liegt bei 13,9:1 (noetig 7).
Drei eigene Fehler beim Bauen, alle von der Pruefung gefunden:
1. Es gibt ZWEI Regeln fuer dieselbe Kachel (Grundform und
Feinschliff). Ich hatte nur die erste umgestellt, die zweite gewann
-- die eigene Kachel waere durchsichtig geblieben.
2. Die Pruefung las backgroundColor und pruefte den Alphawert. Eine
Kachel mit einem VERLAUF hat dort rgba(0,0,0,0); sie meldete
"durchsichtig" bei einer Kachel, die voellig deckt. Jetzt werden
zwei Bildpunkte verglichen, einmal mit und einmal ohne Buehnenbild
-- das misst die Sache selbst, nicht ihren Stellvertreter.
3. Dieselbe Pruefung suchte nur die rgba-Schreibweise. Chrome gibt
das Ergebnis von color-mix als color(srgb r g b / a) zurueck; der
Rueckfall war "Alpha 1", und sie meldete "deckt" bei einer
Flaeche, die durchscheint. Genau das Gegenteil.
pruef-chatkachel.mjs: 27 Pruefungen, mit eingebauter Gegenprobe (auf
der freien Flaeche MUSS sich etwas aendern, sonst misst der Vergleich
nichts). pruef-chat-optik und pruef-erwaehnung unveraendert gruen.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -30,6 +30,124 @@
|
||||
'use strict';
|
||||
|
||||
const $ = (id) => document.getElementById(id);
|
||||
|
||||
/* =====================================================================
|
||||
MEINE KACHEL (20.09.2026)
|
||||
|
||||
Filipe: „jeder account soll seine kachel personalisieren koennen."
|
||||
|
||||
DIE TABELLE IST LEER UND WIRD GEFUELLT. Sie steht nicht als feste
|
||||
Liste hier: Die zwoelf Toene gehoeren dem Server (CHAT_KACHELN in
|
||||
workspace-chat.js), und eine zweite Fassung im Browser waere beim
|
||||
dreizehnten die vergessene -- dieselbe Krankheit wie bei KANAL_WORT
|
||||
auf dem Highlight-Brett, die heute behoben wurde.
|
||||
|
||||
WOZU SIE HIER GEBRAUCHT WIRD: Die Nachricht bringt einen
|
||||
SCHLUESSEL mit („moos"), keine Farbe. Waere die Farbe selbst in der
|
||||
Nachricht, stuende ein CSS-Wert aus der Datenbank in der Seite --
|
||||
und ein vertippter oder boeswilliger Eintrag koennte faerben, was
|
||||
er will. So kommt nur durch, was in der Tabelle steht. */
|
||||
const KACHEL_FARBE = Object.create(null);
|
||||
let kachelListe = [];
|
||||
let meineKachel = null;
|
||||
|
||||
async function kachelnLaden() {
|
||||
try {
|
||||
const a2 = await fetch('/workspace/api/chat/kacheln', { credentials: 'same-origin' });
|
||||
if (!a2.ok) return;
|
||||
const d = await a2.json();
|
||||
kachelListe = Array.isArray(d.kacheln) ? d.kacheln : [];
|
||||
meineKachel = d.meine || null;
|
||||
for (const k of kachelListe) KACHEL_FARBE[k.wert] = k.farbe;
|
||||
kachelKnopfZeigen();
|
||||
} catch { /* ohne die Liste bleibt alles beim Standard -- kein Grund
|
||||
zu scheitern, der Chat funktioniert weiter */ }
|
||||
}
|
||||
|
||||
function kachelKnopfZeigen() {
|
||||
const knopf = $('kachel-oeffnen');
|
||||
if (!knopf) return;
|
||||
/* OHNE LISTE KEIN KNOPF. Ein Knopf, der eine leere Auswahl oeffnet,
|
||||
ist schlimmer als keiner -- man drueckt ihn und sucht den Fehler
|
||||
bei sich. */
|
||||
knopf.hidden = kachelListe.length === 0;
|
||||
const probe = knopf.querySelector('.chat__kachelknopf-probe');
|
||||
if (probe) {
|
||||
probe.style.background = KACHEL_FARBE[meineKachel] || KACHEL_FARBE.grund || '#131a25';
|
||||
}
|
||||
}
|
||||
|
||||
function kachelwahlBauen() {
|
||||
const gitter = $('kachel-gitter');
|
||||
if (!gitter) return;
|
||||
gitter.textContent = '';
|
||||
for (const k of kachelListe) {
|
||||
const b = el('button', 'chat-kachelwahl__ton');
|
||||
b.type = 'button';
|
||||
b.dataset.wert = k.wert;
|
||||
b.style.background = k.farbe;
|
||||
b.setAttribute('role', 'radio');
|
||||
/* DER NAME GEHOERT DAZU, nicht nur die Farbe. Wer Farben schlecht
|
||||
unterscheidet, waehlt sonst zwoelf Mal dasselbe Kaestchen --
|
||||
und ein Vorleseprogramm saehe zwoelf namenlose Knoepfe. */
|
||||
b.setAttribute('aria-label', k.name);
|
||||
b.title = k.name;
|
||||
b.setAttribute('aria-checked', String((meineKachel || 'grund') === k.wert));
|
||||
/* EINE VORSCHAU MIT ECHTEM TEXT, nicht nur ein Farbfleck: Gewaehlt
|
||||
wird ja nicht die Farbe, sondern wie die eigene Nachricht
|
||||
aussieht. */
|
||||
b.append(el('span', 'chat-kachelwahl__wort', 'Aa'));
|
||||
b.addEventListener('click', () => kachelSetzen(k.wert, b));
|
||||
gitter.append(b);
|
||||
}
|
||||
}
|
||||
|
||||
async function kachelSetzen(wert, knopf) {
|
||||
const vorher = meineKachel;
|
||||
/* SOFORT UMSTELLEN, dann speichern. Wer eine Farbe antippt und eine
|
||||
halbe Sekunde nichts sieht, tippt noch einmal. Geht es schief,
|
||||
wird es zurueckgenommen -- und zwar sichtbar. */
|
||||
meineKachel = (wert === 'grund') ? null : wert;
|
||||
for (const b of knopf.parentElement.querySelectorAll('.chat-kachelwahl__ton')) {
|
||||
b.setAttribute('aria-checked', String(b === knopf));
|
||||
}
|
||||
kachelKnopfZeigen();
|
||||
eigeneKachelnFaerben();
|
||||
try {
|
||||
const a2 = await hole('/workspace/api/chat/kachel', {
|
||||
method: 'PUT', headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ kachel: wert }),
|
||||
});
|
||||
if (!a2.ok) throw new Error('abgelehnt');
|
||||
} catch {
|
||||
meineKachel = vorher;
|
||||
kachelKnopfZeigen();
|
||||
eigeneKachelnFaerben();
|
||||
kachelwahlBauen();
|
||||
melde('Die Farbe konnte nicht gespeichert werden.');
|
||||
}
|
||||
}
|
||||
|
||||
/** Die eigenen Nachrichten im offenen Verlauf sofort umfaerben.
|
||||
*
|
||||
* OHNE NEU ZU LADEN: Der Verlauf neu zu holen hiesse, beim Faerben
|
||||
* nach unten zu springen und die Stelle zu verlieren, an der man
|
||||
* gerade liest. Die Farbe steht ohnehin nur an der Kachel. */
|
||||
function eigeneKachelnFaerben() {
|
||||
const farbe = KACHEL_FARBE[meineKachel] || null;
|
||||
for (const z of document.querySelectorAll('.chat-nachricht[data-selbst="ja"] .chat-nachricht__blase')) {
|
||||
if (farbe) z.style.setProperty('--kachel', farbe);
|
||||
else z.style.removeProperty('--kachel');
|
||||
}
|
||||
}
|
||||
|
||||
function kachelwahlBedienen() {
|
||||
const knopf = $('kachel-oeffnen'), dlg = $('kachel-wahl'), zu = $('kachel-zu');
|
||||
if (!knopf || !dlg) return;
|
||||
knopf.addEventListener('click', () => { kachelwahlBauen(); dlg.showModal(); });
|
||||
zu?.addEventListener('click', () => dlg.close());
|
||||
}
|
||||
|
||||
const el = (tag, klasse, text) => {
|
||||
const k = document.createElement(tag);
|
||||
if (klasse) k.className = klasse;
|
||||
@@ -1090,6 +1208,23 @@
|
||||
if (n.angeheftet) zeile.dataset.angeheftet = 'ja';
|
||||
|
||||
const blase = el('div', 'chat-nachricht__blase');
|
||||
/* DIE EIGENE KACHELFARBE (20.09.2026).
|
||||
|
||||
Filipe: „jeder account soll seine kachel personalisieren
|
||||
koennen."
|
||||
|
||||
Der Wert kommt vom Server als SCHLUESSEL, nicht als Farbe --
|
||||
hier wird er in der Tabelle nachgeschlagen, die ebenfalls vom
|
||||
Server kam. Waere die Farbe selbst in der Nachricht, stuende
|
||||
ein CSS-Wert aus der Datenbank in der Seite; ein vertippter
|
||||
oder boeswilliger Eintrag koennte dann faerben, was er will.
|
||||
|
||||
Kein Wert heisst Standard, und dafuer steht gar nichts da --
|
||||
der Rueckfall liegt im Stilblatt (`var(--kachel, …)`). Eine
|
||||
Zeile, die die Standardfarbe noch einmal hinschreibt, waere
|
||||
eine zweite Stelle, an der sie stimmen muss. */
|
||||
const kFarbe = KACHEL_FARBE[n.von_kachel];
|
||||
if (kFarbe) blase.style.setProperty('--kachel', kFarbe);
|
||||
if (!gleicheFolge && !n.selbst && offen.art !== 'direkt') {
|
||||
blase.append(el('p', 'chat-nachricht__von', n.von));
|
||||
}
|
||||
@@ -2811,6 +2946,11 @@
|
||||
window.werZeigen?.(ich);
|
||||
|
||||
await raeumeLaden();
|
||||
/* DIE KACHELN VOR DEM ERSTEN VERLAUF. Kaemen sie danach, stuenden
|
||||
die ersten Nachrichten kurz in Standardfarbe und faerbten sich
|
||||
dann um -- eine Seite, die sich unter den Fingern aendert. */
|
||||
await kachelnLaden();
|
||||
kachelwahlBedienen();
|
||||
stromOeffnen();
|
||||
unterbauBeobachten();
|
||||
unterbauMessen();
|
||||
|
||||
Reference in New Issue
Block a user