Chat: Avatare koennen Profilbilder tragen
avatarKreis() zeigt ein Foto, sobald eines unter assets/eigene/portrait-<kuerzel>.<endung> 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) <noreply@anthropic.com>
This commit is contained in:
1 parent
a94c1985fc
commit
20d26d3383
2 files changed
+54
-6
No files matched your search
@@ -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-<kürzel>.<endung>` 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
|
||||
|
||||
+40
-6
@@ -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 '<circle cx="' + n1(cx) + '" cy="' + n1(cy) + '" r="' + r + '" fill="' +
|
||||
MARKE.flaeche + '" stroke="' + MARKE.rand + '" stroke-width="1.2"/>' +
|
||||
uiText(cx, cy + r * 0.3, kuerzel, r * 0.75, 800, MARKE.zeichen, { anker: "middle" });
|
||||
}
|
||||
const id = "pfoto" + (++pfNr);
|
||||
return '<clipPath id="' + id + '"><circle cx="' + n1(cx) + '" cy="' + n1(cy) +
|
||||
'" r="' + r + '"/></clipPath>' +
|
||||
'<image href="' + bild + '" x="' + n1(cx - r) + '" y="' + n1(cy - r) + '" width="' +
|
||||
n1(2 * r) + '" height="' + n1(2 * r) +
|
||||
'" preserveAspectRatio="xMidYMid slice" clip-path="url(#' + id + ')"/>' +
|
||||
'<circle cx="' + n1(cx) + '" cy="' + n1(cy) + '" r="' + r +
|
||||
'" fill="none" stroke="' + MARKE.rand + '" stroke-width="1.2"/>';
|
||||
}
|
||||
|
||||
/* 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 += '<circle cx="' + n1(mx + 20) + '" cy="' + n1(my) + '" r="20" fill="' +
|
||||
MARKE.flaeche + '" stroke="' + MARKE.rand + '" stroke-width="1.2"/>' +
|
||||
uiText(mx + 20, my + 6, c.kuerzel, 15, 800, MARKE.zeichen, { anker: "middle" });
|
||||
g += avatarKreis(mx + 20, my, 20, c.kuerzel);
|
||||
} else {
|
||||
g += '<rect x="' + n1(mx) + '" y="' + n1(my - 20) + '" width="40" height="40" rx="11" ' +
|
||||
'fill="' + MARKE.flaeche + '" stroke="' + MARKE.rand + '" stroke-width="1.2"/>';
|
||||
@@ -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 += '<circle cx="' + n1(x + 20) + '" cy="' + n1(y + 22) + '" r="20" fill="' +
|
||||
MARKE.flaeche + '" stroke="' + MARKE.rand + '" stroke-width="1.2"/>' +
|
||||
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 += '<g filter="url(#hgschatten)"><path d="' + kontur + '" fill="' +
|
||||
|
||||
Reference in new issue
Block a user