From 20d26d3383a72c0d7c97564ca5d3de439b928871 Mon Sep 17 00:00:00 2001 From: DeeCee03 Date: Thu, 27 Aug 2026 19:57:00 +0200 Subject: [PATCH] Chat: Avatare koennen Profilbilder tragen avatarKreis() zeigt ein Foto, sobald eines unter assets/eigene/portrait-. liegt -- portrait-sk, portrait-mb, portrait-tw, portrait-ms -- rund beschnitten, mit demselben Rand wie der Kuerzelkreis. Ist keines da, steht wie bisher das Kuerzel im Kreis. Hochladen geht ueber "Eigene Bilder" in der Seite; preloadAssets() holt alles aus assets/eigene ohnehin mit, der Export bekommt sie damit als Daten-URL. Mit einem Testbild durchgefahren und wieder entfernt. Keine Fotos im Repo, und zwar mit Absicht: das Pitch-Paket laedt seine Portraits von Unsplash -- vier Aufnahmen echter, erkennbarer Menschen. Die Lizenz deckt das Foto, nicht das Recht am eigenen Bild. Ein fremdes Gesicht als "Sandra Koch, Projektleitung" in einen oeffentlichen Beitrag zu setzen, ist etwas anderes als ein Klickdummy fuer einen Kundentermin. Co-Authored-By: Claude Opus 5 (1M context) --- POST-6.md | 14 ++++++++++++++ post6.html | 46 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/POST-6.md b/POST-6.md index 789574a..8a42eb0 100644 --- a/POST-6.md +++ b/POST-6.md @@ -117,6 +117,20 @@ Familien in einer Liste, und keine davon sagte etwas, das die Zeile nicht schon sagt. Die Kürzel unterscheiden die Personen, dafür braucht es keine vier Farbtöne. +**Profilbilder sind vorbereitet, aber keine drin.** `avatarKreis()` zeigt ein +Foto, sobald eines unter `assets/eigene/portrait-.` liegt (also +`portrait-sk`, `portrait-mb`, `portrait-tw`, `portrait-ms`), rund beschnitten +mit demselben Rand wie der Kürzelkreis; sonst steht wie bisher das Kürzel da. +Hochladen geht über „Eigene Bilder" in der Seite, `preloadAssets()` holt alles +aus `assets/eigene` ohnehin mit, und der Export bekommt sie damit als Daten-URL +statt als Verweis. + +Warum keine im Repo: das Pitch-Paket lädt seine Portraits von Unsplash +(`PORTRAITS` in `GeneralTeamChatPage.tsx`, vier Aufnahmen echter, erkennbarer +Menschen). Die Lizenz deckt das Foto, nicht das Recht am eigenen Bild. Ein +fremdes Gesicht als „Sandra Koch, Projektleitung" in einen öffentlichen Beitrag +zu setzen, ist etwas anderes als ein Klickdummy für einen Kundentermin. + **Die Plakette für Ungelesenes trägt eine Zahl und ist grün.** In der Quelle ist `unread` ein Wahrheitswert und der Punkt violett. Beides ist geändert: violett ist im Produkt die Farbe der Projekte, das Kanalsymbol in derselben diff --git a/post6.html b/post6.html index e175768..5b51c53 100644 --- a/post6.html +++ b/post6.html @@ -2603,6 +2603,44 @@ if (location.search.indexOf("nur=anim") >= 0) ohnehin die Farbe der Plakette daneben. */ const MARKE = { flaeche: "#DCFCE4", rand: "#B7EDC6", zeichen: "#148134" }; + /* Profilbilder. Solange keine da sind, steht das Kuerzel im Kreis -- so wie + jetzt. Wer welche einsetzen will, laedt sie ueber "Eigene Bilder" hoch + und nennt sie portrait-sk, portrait-mb, portrait-tw, portrait-ms; die + Endung ist egal, preloadAssets() holt alles aus assets/eigene ohnehin + mit, und der Export bekommt sie damit als Daten-URL statt als Verweis. + + Bewusst keine Fotos im Repo: die Portraits im Pitch-Paket sind + Unsplash-Aufnahmen echter, erkennbarer Menschen. Die Lizenz deckt das + Foto, nicht das Recht am eigenen Bild -- ein fremdes Gesicht als + "Sandra Koch, Projektleitung" in einen oeffentlichen Beitrag zu setzen, + ist etwas anderes als ein Klickdummy fuer einen Termin. */ + let pfNr = 0; + const portrait = kuerzel => { + if (!kuerzel) return null; + const su = "/eigene/portrait-" + kuerzel.toLowerCase() + "."; + const t = Object.keys(assets).find(k => k.includes(su)); + return t ? assets[t] : null; + }; + + /* Ein runder Avatar: Foto, wenn eines da ist, sonst das Kuerzel. Der Rand + liegt in beiden Faellen darueber, damit die Kante gleich aussieht. */ + function avatarKreis(cx, cy, r, kuerzel) { + const bild = portrait(kuerzel); + if (!bild) { + return '' + + uiText(cx, cy + r * 0.3, kuerzel, r * 0.75, 800, MARKE.zeichen, { anker: "middle" }); + } + const id = "pfoto" + (++pfNr); + return '' + + '' + + ''; + } + /* Die Chatliste links. type steuert das Sinnbild davor: ein Projekt bekommt den Aktenkoffer auf farbigem Grund, eine Gruppe die Personen, eine Direktnachricht das Kuerzel des Menschen -- so macht es ChatAvatar. */ @@ -2655,9 +2693,7 @@ if (location.search.indexOf("nur=anim") >= 0) } const mx = x + 16, my = y + ZEILE_H / 2; if (c.art === "direkt") { - g += '' + - uiText(mx + 20, my + 6, c.kuerzel, 15, 800, MARKE.zeichen, { anker: "middle" }); + g += avatarKreis(mx + 20, my, 20, c.kuerzel); } else { g += ''; @@ -2781,9 +2817,7 @@ if (location.search.indexOf("nur=anim") >= 0) const bx = m.mein ? x + b - ma.breite : x + 52; let g = ""; if (!m.mein) { - g += '' + - uiText(x + 20, y + 28, m.kuerzel, 15, 800, MARKE.zeichen, { anker: "middle" }); + g += avatarKreis(x + 20, y + 22, 20, m.kuerzel); } const kontur = rundRechteck(bx, y, ma.breite, ma.hoehe, 14); g += '