Chatliste: gruene Plakette mit Zahl, Gruppe ohne Allerwelts-Symbol

Der Punkt fuer Ungelesenes war violett und leer. Violett ist im Produkt die
Farbe der Projekte -- das Kanalsymbol in derselben Zeile traegt sie schon, und
ein zweites violettes Zeichen daneben konkurriert damit, statt etwas anderes zu
sagen. Ein farbloser Punkt sagt ausserdem nur "da war was". Jetzt gruen, mit
der Zahl der ungelesenen Nachrichten darin, wie in jedem Messenger, den ein
Betrieb kennt. Die Uhrzeit derselben Zeile faerbt mit.

Die Zahlen (3, 2, 1) stehen nicht in der Quelle, dort ist unread ein
Wahrheitswert. Sie sind die einzigen erfundenen Werte im Post und stehen so in
POST-6.md.

Die Gruppe trug FeatherUsers -- das Zwei-Personen-Piktogramm, das in jeder
zweiten Oberflaeche steckt und danach aussieht. Jetzt zwei ueberlappende
Avatarscheiben, wie Teams und Linear sie an derselben Stelle zeigen; sie
sprechen dieselbe Sprache wie die Kuerzelkreise der Direktnachrichten daneben.
Ohne Buchstaben, weil die Mitglieder nirgends benannt sind.

Dabei gefunden: nach dem Vergroessern des Ausschnitts auf Slide 2 hatte ich
kollision.mjs mit Argument 1 laufen lassen -- das ist Slide 1. Auf Slide 2 ragte
das hinterste, gedrehte Blatt des Stapels fuenf Einheiten unter den Kasten.
stapelRand() rechnet den Ueberstand fuer die unskalierte Groesse, die
Skalierung vergroessert ihn mit. Der Kasten kommt jetzt aus dem skalierten
Stapel.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dejanandClaude Opus 5 committed 2026-08-27 18:41:39 +02:00
1 parent efcb864db1
commit a2cb7cbf6c
3 files changed
+79 -16

No files matched your search

+51 -15
View File
@@ -2611,12 +2611,12 @@ if (location.search.indexOf("nur=anim") >= 0)
Direktnachricht das Kuerzel des Menschen -- so macht es ChatAvatar. */
const CHATS = [
{ titel: "# waermepumpe-mueller", vorschau: "Tobias: @Michael Fotos sind im Projektordner.",
zeit: "14:32", meta: "P-2026-0042", art: "projekt", ungelesen: true, pin: true, aktiv: true },
zeit: "14:32", meta: "P-2026-0042", art: "projekt", ungelesen: 3, pin: true, aktiv: true },
{ titel: "Sandra Koch", vorschau: "Montagetermin ist mit der Familie abgestimmt.",
zeit: "13:48", meta: "Projektleitung", art: "direkt", ungelesen: true, pin: true,
zeit: "13:48", meta: "Projektleitung", art: "direkt", ungelesen: 2, pin: true,
kuerzel: "SK", farbe: "blau" },
{ titel: "Angebot_v1.pdf · Rückfrage", vorschau: "Maike: Geprüft und freigegeben.",
zeit: "12:05", meta: "Dokumenten-Thread", art: "projekt", ungelesen: true },
zeit: "12:05", meta: "Dokumenten-Thread", art: "projekt", ungelesen: 1 },
{ titel: "Tobias Wagner", vorschau: "Passt, der Termin steht bei mir.",
zeit: "11:26", meta: "Montage", art: "direkt", kuerzel: "TW", farbe: "violett" },
{ titel: "Montage Team Süd", vorschau: "Mehmet: Werkzeugliste ist abgeschickt.",
@@ -2629,6 +2629,12 @@ if (location.search.indexOf("nur=anim") >= 0)
zeit: "25.07.", meta: "Service & Wartung", art: "projekt" },
];
/* Gruen statt violett fuer alles Ungelesene: die Plakette und die Uhrzeit
daneben. Violett ist im Produkt die Farbe der Projekte -- das Symbol des
Kanals traegt sie, und ein zweites violettes Zeichen in derselben Zeile
konkurriert damit, statt etwas anderes zu sagen. */
const UNGELESEN = "#148134";
const LISTE_B = 372, ZEILE_H = 96;
/* Eine Zeile der Chatliste. Drei Zeilen, wie im Original:
@@ -2657,12 +2663,30 @@ if (location.search.indexOf("nur=anim") >= 0)
'" stroke="' + CHAT_RAND + '" stroke-width="1.2"/>' +
uiText(mx + 20, my + 6, c.kuerzel, 15, 800, av.text, { anker: "middle" });
} else {
const projekt = c.art === "projekt";
g += '<rect x="' + n1(mx) + '" y="' + n1(my - 20) + '" width="40" height="40" rx="11" fill="' +
(projekt ? "#F0E7FF" : "#FAFAFA") + '" stroke="' + (projekt ? "#e4d4ff" : CHAT_RAND) +
'" stroke-width="1.2"/>';
g += feather(projekt ? "briefcase" : "users", mx + 20, my, 20,
projekt ? "#691CD4" : CHAT_TEXT3, 1.9);
if (c.art === "projekt") {
g += '<rect x="' + n1(mx) + '" y="' + n1(my - 20) + '" width="40" height="40" rx="11" ' +
'fill="#F0E7FF" stroke="#e4d4ff" stroke-width="1.2"/>';
g += feather("briefcase", mx + 20, my, 20, "#691CD4", 1.9);
} else {
/* Die Gruppe traegt zwei ueberlappende Scheiben und kein Symbol. Das
Zwei-Personen-Piktogramm aus dem Feather-Satz steckt in jeder
zweiten Oberflaeche und sieht danach aus; zwei versetzte Avatare
sind das, was Teams und Linear an derselben Stelle zeigen, und sie
sprechen dieselbe Sprache wie die Kuerzelkreise der
Direktnachrichten daneben. Ohne Buchstaben, weil wir die Mitglieder
dieser Gruppe nicht kennen -- wie viele es sind, steht in der
Zeile darunter. */
/* Kontur in der Textfarbe des jeweiligen Avatars, nicht in der
allgemeinen Randfarbe: mit CHAT_RAND verschwammen die beiden
Scheiben bei Listengroesse zu einem Fleck. */
const a1 = AVATAR.blau, a2 = AVATAR.violett;
g += '<circle cx="' + n1(mx + 13) + '" cy="' + n1(my - 7) + '" r="13" fill="' +
a1.flaeche + '" stroke="' + a1.text + '" stroke-width="1.4" opacity=".9"/>';
g += '<circle cx="' + n1(mx + 27) + '" cy="' + n1(my + 7) + '" r="14.6" ' +
'fill="#FFFFFF"/>';
g += '<circle cx="' + n1(mx + 27) + '" cy="' + n1(my + 7) + '" r="13" fill="' +
a2.flaeche + '" stroke="' + a2.text + '" stroke-width="1.4" opacity=".9"/>';
}
}
const tx = mx + 52, rechts = x + LISTE_B - 16, frei = rechts - tx;
@@ -2671,13 +2695,20 @@ if (location.search.indexOf("nur=anim") >= 0)
g += uiText(tx, y + 30, umbrechen(c.titel, frei - zeitB - 12, 17, 700, 1)[0],
17, 700, CHAT_TEXT);
g += uiText(rechts, y + 30, c.zeit, 14, 500,
c.ungelesen ? "#691CD4" : CHAT_TEXT3, { anker: "end" });
c.ungelesen ? UNGELESEN : CHAT_TEXT3, { anker: "end" });
// Zeile 2: Vorschau, rechts der Punkt fuer Ungelesenes.
g += uiText(tx, y + 54, umbrechen(c.vorschau, frei - (c.ungelesen ? 22 : 0), 15, 500, 1)[0],
/* Zeile 2: Vorschau, rechts die Plakette. Sie traegt die Zahl der
ungelesenen Nachrichten und ist gruen -- ein farbloser Punkt sagt nur
"da war was", eine Zahl sagt, wie viel. So macht es jeder Messenger,
den ein Betrieb kennt. */
const zahl = c.ungelesen ? String(c.ungelesen) : "";
const zb = zahl ? Math.max(22, messen(zahl, 13, 800) + 14) : 0;
g += uiText(tx, y + 54, umbrechen(c.vorschau, frei - (zb ? zb + 8 : 0), 15, 500, 1)[0],
15, 500, c.ungelesen ? CHAT_TEXT : CHAT_TEXT2);
if (c.ungelesen) {
g += '<circle cx="' + n1(rechts - 6) + '" cy="' + n1(y + 49) + '" r="6" fill="#691CD4"/>';
if (zahl) {
g += '<rect x="' + n1(rechts - zb) + '" y="' + n1(y + 38) + '" width="' + n1(zb) +
'" height="22" rx="11" fill="' + UNGELESEN + '"/>';
g += uiText(rechts - zb / 2, y + 53, zahl, 13, 800, "#FFFFFF", { anker: "middle" });
}
// Zeile 3: die Zuordnung, rechts die Nadel.
@@ -3072,7 +3103,12 @@ if (location.search.indexOf("nur=anim") >= 0)
const LISTE_SKALA = 1.28;
const skB = sb * LISTE_SKALA, skH = sh * LISTE_SKALA, skM = m * LISTE_SKALA;
const LX = 388; // wo der Kasten der Liste anfaengt
const W = LX + skB + skM, H = 736;
/* Der Kasten muss den skalierten Stapel samt Ueberstand fassen. Mit fest
gesetzten 736 ragte das hinterste, gedrehte Blatt fuenf Einheiten
darunter heraus -- stapelRand() rechnet den Ueberstand fuer die
unskalierte Groesse, und die Skalierung vergroessert ihn mit. */
const W = LX + skB + skM;
const H = Math.max(736, Math.ceil(skH + 2 * skM + 6));
let g = "";
/* Fest gesetzte Lagen statt gewuerfelter: ein Zufallsgenerator gaebe bei