Punkt 15: Der Chat bekommt Suche, Antworten mit Zitat und die Ungelesen-Linie
Wunsch Filipe: "ich will dass du diese seite viel krasser und detaillierter machst, ich will dass du dich informierst und alles reinsetzt was wir noch gebrauchen koennten." NICHT ALLES, SONDERN WAS TAEGLICH FEHLT. Der Chat konnte schon Raeume, Verlauf, Gelesen-Stand, Live-Zustellung, Gruppen und Zuruecknehmen. Drei Dinge fehlten, und jedes davon kostet ohne es echte Zeit: 1. SUCHE IN DEN NACHRICHTEN. Ein Chat ohne sie ist ab dem zweiten Monat ein Archiv, in dem man nichts findet. Ein Suchfeld gab es -- es durchsuchte aber nur die NAMEN der Gespraeche, also die kleinere Haelfte. Jetzt durchsucht dasselbe Feld beides und zeigt die Fundstellen UNTER der Gespraechsliste: Wer "Patrick" eingibt, will vielleicht das Gespraech und vielleicht die Nachricht -- ein Umschalter haette ihn zwingen wollen, das vorher zu wissen. 2. ANTWORTEN MIT ZITAT. Zu zweit weiss man meistens, worauf sich etwas bezieht. In einer Gruppe laufen drei Faeden parallel, und "ja, mach das" kann alles heissen. Das Zitat steht IN der Blase (es gehoert zur Antwort, nicht darueber) und fuehrt per Klick zur Stelle. 3. DIE LINIE "AB HIER NEU". Wer nach zwei Tagen zurueckkommt, sucht sonst die Stelle, an der er aufgehoert hat, indem er Uhrzeiten liest. BEWUSST NICHT GEBAUT: Anhaenge (dafuer gibt es den Dateien-Bereich mit Rechten und Ablauf), Reaktionen (eine vierte Sache, bevor die drei sich bewaehrt haben) und Tipp-Anzeigen (dauernder Verkehr fuer eine Auskunft, die man in zwei Sekunden ohnehin sieht). DIE SICHERHEIT DER SUCHE STEHT IM JOIN, nicht in einer nachtraeglichen Pruefung: `chat_teilnehmer` wird mit der eigenen Personenkennung verbunden, und was dort nicht drinsteht, kommt gar nicht erst aus der Datenbank. Ein Filter, der erst hinterher aussortiert, ist eine Zeile davon entfernt, vergessen zu werden. Ebenso beim Zitat: Worauf geantwortet wird, muss im SELBEN Raum liegen -- sonst koennte jemand die Kennung aus einem fremden Gespraech mitschicken, und beim Empfaenger stuende ein Zitat aus einem Raum, den er nie gesehen hat. DREI FEHLER, DIE DER DURCHLAUF GEFUNDEN HAT: 1. `ESCAPE '\'` IN EINEM TEMPLATE-LITERAL. Dort ist `\'` eine Fluchtsequenz fuer das Anfuehrungszeichen -- SQLite bekam ein LEERES Fluchtzeichen und antwortete "ESCAPE expression must be a single character". Die Suche war damit komplett tot. Kein Syntaxfehler, kein Warnhinweis: Erst der Aufruf mit echten Daten hat es gezeigt. 2. DIE MASKIERUNG KANNTE ZWEI VON DREI ZEICHEN. `%` und `_` waren dabei, der Backslash nicht -- ausgerechnet das Fluchtzeichen selbst. Geprueft wird das jetzt an der ZEILE AUS DER DATEI, nicht an einem Nachbau: Mein erster Test hat die Maskierung nachgebaut und dabei die Shell-Maskierung mitgeschleppt -- er meldete einen Fehler, den nur er hatte. 3. DIE UNGELESEN-LINIE SCHIEN NICHT ZU FUNKTIONIEREN. Sie tat es -- mein Testaufbau war falsch: Filipes Seite war noch offen, die neuen Nachrichten kamen ueber den Live-Strom an und wurden sofort als gelesen gemeldet. Es gab schlicht nichts Ungelesenes. Erst als er die Seite verlaesst, bevor Patrick schreibt, steht die Linie da -- und zwar genau vor "Neu von Patrick, eins", und beim zweiten Oeffnen ist sie weg. Der Gelesen-Stand wird deshalb beim OEFFNEN mitgeschickt, bevor er gesetzt wird -- eine Zeile spaeter waere er immer die letzte Nachricht, und die Linie staende nie irgendwo. Ohne Volltextindex, mit Absicht: `LIKE` liest die Tabelle, und bei einem Team dieser Groesse sind das einige tausend Zeilen. Ein FTS5-Index waere eine zweite Tabelle, die synchron gehalten werden muss -- genau daran gehen solche Sachen kaputt. Wenn der Verlauf sechsstellig wird, ist das der Zeitpunkt dafuer, nicht heute. Geprueft: pruef-chat, pruef-chat-optik, pruef-css-klassen, pruef-workspace-seiten, pruef-handy -- alle in Ordnung. Dazu im Browser durchgespielt: Zitat gesetzt und gelesen, Suche nach "Bitrate" (1 Treffer), nach "100 %" (1 Treffer -- die Maskierung haelt), nach Unsinn (0), einbuchstabige Suche (zu kurz), Antwortleiste mit dem richtigen Namen, Ungelesen-Linie an der richtigen Stelle und beim zweiten Oeffnen weg. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -636,3 +636,161 @@
|
||||
.chat-raum__knopf[data-an="ja"] { box-shadow: none; border: 1px solid CanvasText; }
|
||||
.chat-raum__zeichen, .chat-nachricht__zeichen { background: Canvas; box-shadow: none; }
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
DREI DINGE, DIE DEM CHAT GEFEHLT HABEN (Punkt 15, 09.09.2026)
|
||||
|
||||
Filipe: "ich will dass du diese seite viel krasser und detaillierter
|
||||
machst, ich will dass du dich informierst und alles reinsetzt was
|
||||
wir noch gebrauchen könnten."
|
||||
|
||||
Nicht alles, sondern das, was hier täglich fehlt. Der Chat konnte
|
||||
schon Räume, Verlauf, Gelesen-Stand, Live-Zustellung, Gruppen und
|
||||
Zurücknehmen. Was fehlte:
|
||||
|
||||
1. SUCHE IN DEN NACHRICHTEN. Ein Chat ohne sie ist ab dem zweiten
|
||||
Monat ein Archiv, in dem man nichts findet. Das Suchfeld gab es
|
||||
— es durchsuchte aber nur die NAMEN der Gespräche.
|
||||
2. ANTWORTEN MIT ZITAT. Zu zweit weiß man meist, worauf sich etwas
|
||||
bezieht. In einer Gruppe laufen drei Fäden parallel, und "ja,
|
||||
mach das" kann alles heißen.
|
||||
3. DIE LINIE "AB HIER NEU". Wer nach zwei Tagen zurückkommt, sucht
|
||||
sonst die Stelle, an der er aufgehört hat, indem er Uhrzeiten
|
||||
liest.
|
||||
|
||||
Bewusst NICHT gebaut: Anhänge (dafür gibt es den Dateien-Bereich mit
|
||||
Rechten und Ablauf), Reaktionen (eine vierte Sache, bevor die drei
|
||||
sich bewährt haben) und Tipp-Anzeigen (sie kosten dauernd Verkehr
|
||||
und sagen nichts, was man nicht in zwei Sekunden sieht).
|
||||
===================================================================== */
|
||||
|
||||
/* ---- Das Zitat in der Blase ---------------------------------------- */
|
||||
.chat-zitat {
|
||||
display: block; width: 100%; text-align: left;
|
||||
margin: 0 0 7px; padding: 6px 10px 6px 11px;
|
||||
border: 0; border-radius: 0;
|
||||
/* Der senkrechte Strich links ist das Zeichen für ein Zitat -- in
|
||||
jedem Mailprogramm seit dreißig Jahren dasselbe. */
|
||||
box-shadow: inset 3px 0 0 color-mix(in srgb, var(--akzent) 60%, transparent);
|
||||
background: rgba(255, 255, 255, .05);
|
||||
color: var(--text-leise);
|
||||
font: inherit; cursor: pointer;
|
||||
transition: background var(--tempo);
|
||||
}
|
||||
.chat-zitat:hover { background: rgba(255, 255, 255, .09); }
|
||||
.chat-zitat__von {
|
||||
display: block;
|
||||
font-size: .74rem; font-weight: 700;
|
||||
color: color-mix(in srgb, var(--akzent) 70%, #ffffff);
|
||||
}
|
||||
.chat-zitat__text {
|
||||
display: block;
|
||||
font-size: .8rem; line-height: 1.35;
|
||||
/* Zwei Zeilen reichen: Es ist ein Hinweis auf die Stelle, nicht ihre
|
||||
Wiederholung. */
|
||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Die zitierte Nachricht, wenn man hinspringt -- kurz hervorgehoben.
|
||||
Ein Sprung ohne Markierung lässt einen raten, welche Zeile gemeint
|
||||
war. */
|
||||
.chat-nachricht[data-hervor="ja"] .chat-nachricht__blase {
|
||||
box-shadow: 0 0 0 2px color-mix(in srgb, var(--akzent) 65%, transparent);
|
||||
transition: box-shadow .4s ease;
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.chat-nachricht[data-hervor="ja"] .chat-nachricht__blase { transition: none; }
|
||||
}
|
||||
|
||||
/* ---- Die Linie "ab hier neu" --------------------------------------- */
|
||||
.chat-neu {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
margin: 14px 2px 10px;
|
||||
color: #ff8f98;
|
||||
font-size: .72rem; font-weight: 700;
|
||||
letter-spacing: .1em; text-transform: uppercase;
|
||||
}
|
||||
.chat-neu::before, .chat-neu::after {
|
||||
content: ""; flex: 1; height: 1px;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 143, 152, .5));
|
||||
}
|
||||
.chat-neu::after { background: linear-gradient(90deg, rgba(255, 143, 152, .5), transparent); }
|
||||
.chat-neu__text { flex: none; }
|
||||
|
||||
/* ---- Die Antwortleiste über dem Eingabefeld ------------------------ */
|
||||
.antwort-leiste {
|
||||
display: flex; align-items: flex-start; gap: 10px;
|
||||
margin-bottom: 8px; padding: 8px 10px 8px 11px;
|
||||
box-shadow: inset 3px 0 0 var(--akzent);
|
||||
background: rgba(255, 255, 255, .05);
|
||||
}
|
||||
.antwort-leiste[hidden] { display: none; }
|
||||
.antwort-leiste__inhalt { min-width: 0; flex: 1; }
|
||||
.antwort-leiste__schild {
|
||||
/* 0,72 rem = 11,52 px. Mit 0,7 waeren es 11,2 und damit unter der
|
||||
Grundlinie, die pruef-css-klassen haelt. */
|
||||
font-size: .72rem; letter-spacing: .08em; text-transform: uppercase;
|
||||
color: var(--text-still);
|
||||
}
|
||||
.antwort-leiste__von {
|
||||
margin-left: 6px;
|
||||
font-size: .78rem; font-weight: 700;
|
||||
color: color-mix(in srgb, var(--akzent) 70%, #ffffff);
|
||||
}
|
||||
.antwort-leiste__text {
|
||||
display: block;
|
||||
font-size: .82rem; color: var(--text-leise);
|
||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
||||
}
|
||||
.antwort-leiste__weg {
|
||||
flex: none; width: 28px; height: 28px;
|
||||
border: 0; border-radius: 50%;
|
||||
background: rgba(255, 255, 255, .07);
|
||||
color: var(--text-leise); font-size: .9rem; cursor: pointer;
|
||||
}
|
||||
.antwort-leiste__weg:hover { background: rgba(255, 255, 255, .13); color: var(--text); }
|
||||
|
||||
/* ---- Fundstellen in Nachrichten ------------------------------------ */
|
||||
.chat-funde { padding: 4px 10px 12px; }
|
||||
.chat-funde[hidden] { display: none; }
|
||||
.chat-funde__schild {
|
||||
margin: 8px 0 6px;
|
||||
font-size: .72rem; font-weight: 700;
|
||||
letter-spacing: .09em; text-transform: uppercase;
|
||||
color: var(--text-still);
|
||||
}
|
||||
.chat-funde__liste { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
|
||||
.chat-funde__leer { font-size: .84rem; color: var(--text-still); }
|
||||
.chat-fund {
|
||||
display: grid; gap: 2px;
|
||||
width: 100%; padding: 8px 11px;
|
||||
text-align: left; border: 0;
|
||||
clip-path: polygon(7px 0, 100% 0, 100% calc(100% - 7px), calc(100% - 7px) 100%, 0 100%, 0 7px);
|
||||
background: rgba(255, 255, 255, .045);
|
||||
color: var(--text); font: inherit; cursor: pointer;
|
||||
transition: background var(--tempo);
|
||||
}
|
||||
.chat-fund:hover { background: rgba(255, 255, 255, .09); }
|
||||
.chat-fund__kopf { display: flex; justify-content: space-between; gap: 8px; }
|
||||
.chat-fund__raum {
|
||||
font-size: .78rem; font-weight: 700;
|
||||
overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
|
||||
}
|
||||
.chat-fund__wann { flex: none; font-size: .72rem; color: var(--text-still); }
|
||||
.chat-fund__von { font-size: .72rem; color: var(--text-still); }
|
||||
.chat-fund__text {
|
||||
font-size: .82rem; color: var(--text-leise); line-height: 1.35;
|
||||
display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Der Antworten-Knopf am Fuß einer Nachricht -- genauso leise wie
|
||||
"zurücknehmen" daneben. Er ist ein Angebot, keine Aufforderung. */
|
||||
.chat-nachricht__antwort-knopf {
|
||||
border: 0; background: none; padding: 0;
|
||||
font: inherit; font-size: .72rem;
|
||||
color: var(--text-still); cursor: pointer;
|
||||
text-decoration: underline; text-underline-offset: 2px;
|
||||
}
|
||||
.chat-nachricht__antwort-knopf:hover { color: var(--text-leise); }
|
||||
|
||||
Reference in New Issue
Block a user