Messaging: Chat-System mit Offline-First und Server-Push #58

Closed
opened 2026-05-16 17:06:52 +00:00 by jreinemann-euris · 1 comment
jreinemann-euris commented 2026-05-16 17:06:52 +00:00 (Migrated from github.com)

Ziel

Eine Messaging-Funktion in der App einbauen: Benutzer können Text-Nachrichten an andere User senden und empfangen – ähnlich wie WhatsApp, aber einfach gehalten und ohne Schnickschnack.


Funktionale Anforderungen

App-Seite

User-Liste

  • Neue Seite in der App, die alle User anzeigt, die der Server kennt
  • Tippen auf einen User öffnet das Chatfenster mit diesem User

Chatfenster

  • Nachrichten-Verlauf wie bei WhatsApp:
    • Eigene Nachrichten rechts, fremde links
    • Jede Nachricht mit Datumsstempel
    • Zuordnung klar erkennbar
  • Nur Text (kein Bild-/Datei-Upload)
  • Texteingabe-Feld mit Senden-Button am unteren Rand

Senden-Logik (Offline-First)

  • Ist der Server erreichbar → Nachricht direkt senden
  • Ist der Server nicht erreichbar → Nachricht lokal in der App-DB zwischenspeichern
  • Beim nächsten erfolgreichen Server-Kontakt werden zwischengespeicherte Nachrichten automatisch übertragen

Empfangen von Nachrichten (Push)

  • Nachrichten werden per WebSocket-Push vom Server zugestellt
  • Bestehende WebSocket-Infrastruktur (Issue #57) wiederverwenden

Server-Seite

Zuverlässige Zustellung (kein Nachrichtenverlust)

  • Nachricht wird zuerst in die Server-DB geschrieben, dann weitergeleitet
  • Ist der Empfänger-Client online → sofortige Weiterleitung via WebSocket
  • Ist der Empfänger-Client offline → Nachricht bleibt in der DB, bis der Client verbindet
  • Bei Verbindungsaufbau eines Clients → alle ausstehenden Nachrichten zustellen und danach als zugestellt markieren

Datenbankschema (Server)

  • Tabelle messages: id, sender_id, receiver_id, body, sent_at, delivered_at (nullable)

Nicht im Scope

  • Gruppen-Chats
  • Bild-/Datei-Anhänge
  • Lesebestätigungen (Read Receipts)
  • End-to-End-Verschlüsselung
  • Push-Notifications des Betriebssystems (nur In-App-Push via WebSocket)

Abhängigkeiten

  • User-Konzept & Auth (Issue #57) – User-IDs und WebSocket-Infrastruktur müssen vorhanden sein

Akzeptanzkriterien

  • User-Liste zeigt alle Server-User an
  • Chatfenster öffnet sich beim Tippen auf einen User
  • Nachrichten werden korrekt zugeordnet und mit Zeitstempel angezeigt
  • Nachrichten werden lokal gespeichert, wenn Server nicht erreichbar
  • Zwischengespeicherte Nachrichten werden beim nächsten Server-Kontakt automatisch gesendet
  • Server speichert Nachricht in DB bevor er sie weiterleitet
  • Offline-Client erhält alle ausstehenden Nachrichten bei Verbindungsaufbau
## Ziel Eine Messaging-Funktion in der App einbauen: Benutzer können Text-Nachrichten an andere User senden und empfangen – ähnlich wie WhatsApp, aber einfach gehalten und ohne Schnickschnack. --- ## Funktionale Anforderungen ### App-Seite **User-Liste** - Neue Seite in der App, die alle User anzeigt, die der Server kennt - Tippen auf einen User öffnet das Chatfenster mit diesem User **Chatfenster** - Nachrichten-Verlauf wie bei WhatsApp: - Eigene Nachrichten rechts, fremde links - Jede Nachricht mit Datumsstempel - Zuordnung klar erkennbar - Nur Text (kein Bild-/Datei-Upload) - Texteingabe-Feld mit Senden-Button am unteren Rand **Senden-Logik (Offline-First)** - Ist der Server erreichbar → Nachricht direkt senden - Ist der Server nicht erreichbar → Nachricht lokal in der App-DB zwischenspeichern - Beim nächsten erfolgreichen Server-Kontakt werden zwischengespeicherte Nachrichten automatisch übertragen **Empfangen von Nachrichten (Push)** - Nachrichten werden per WebSocket-Push vom Server zugestellt - Bestehende WebSocket-Infrastruktur (Issue #57) wiederverwenden --- ### Server-Seite **Zuverlässige Zustellung (kein Nachrichtenverlust)** - Nachricht wird **zuerst** in die Server-DB geschrieben, **dann** weitergeleitet - Ist der Empfänger-Client online → sofortige Weiterleitung via WebSocket - Ist der Empfänger-Client offline → Nachricht bleibt in der DB, bis der Client verbindet - Bei Verbindungsaufbau eines Clients → alle ausstehenden Nachrichten zustellen und danach als zugestellt markieren **Datenbankschema (Server)** - Tabelle `messages`: `id`, `sender_id`, `receiver_id`, `body`, `sent_at`, `delivered_at` (nullable) --- ## Nicht im Scope - Gruppen-Chats - Bild-/Datei-Anhänge - Lesebestätigungen (Read Receipts) - End-to-End-Verschlüsselung - Push-Notifications des Betriebssystems (nur In-App-Push via WebSocket) --- ## Abhängigkeiten - User-Konzept & Auth (Issue #57) – User-IDs und WebSocket-Infrastruktur müssen vorhanden sein --- ## Akzeptanzkriterien - [ ] User-Liste zeigt alle Server-User an - [ ] Chatfenster öffnet sich beim Tippen auf einen User - [ ] Nachrichten werden korrekt zugeordnet und mit Zeitstempel angezeigt - [ ] Nachrichten werden lokal gespeichert, wenn Server nicht erreichbar - [ ] Zwischengespeicherte Nachrichten werden beim nächsten Server-Kontakt automatisch gesendet - [ ] Server speichert Nachricht in DB bevor er sie weiterleitet - [ ] Offline-Client erhält alle ausstehenden Nachrichten bei Verbindungsaufbau
jreinemann-euris commented 2026-05-16 21:35:47 +00:00 (Migrated from github.com)

Abgeschlossen (2026-05-16)

Zyklen: 1 Implementierungszyklus + 1 Review-Korrektur (N+1-Query)
Tests: 234 Tests, 0 Fehler

Implementierte Artefakte

Shared

  • \MessageDto: id, senderId, senderUsername, receiverId, body, sentAt, deliveredAt?
  • \UserListItemDto: id, username

Server

  • \Messages-Tabelle: id, sender_id, receiver_id, body, sent_at, delivered_at (nullable)
  • \MessageRepository: save, getUndelivered (JOIN), getConversation (JOIN), markDelivered
  • \POST /api/messages, \GET /api/messages/{userId}\
  • \GET /api/users\ (alle User außer eigenem Account)
  • WebSocket-Push bei neuem Message (
    otifyNewMessage)
  • Unzugestellte Nachrichten bei Reconnect automatisch pushen
  • \LoginResponse\ um userId + username erweitert

App

  • \MessageEntity\ + \MessageDao\ (Room, Migration 3→4)
  • \MessageRepositoryImpl: Offline-First (isPending), drain bei WebSocket-Connect
  • \WebSocketEvent.NewMessage\ → automatisch in Room persistiert
  • \AUTH_USER_ID\ in SettingsKeys, bei Login gespeichert
  • \UserListScreen\ + \UserListViewModel: User-Liste mit Tap-Navigation
  • \ChatScreen\ + \ChatViewModel: WhatsApp-Style (eigene Nachrichten rechts, fremde links, Zeitstempel)
  • \MESSAGES-Eintrag in Bottom-Navigation

Nicht im Scope (wie definiert)

  • Gruppen-Chats, Bild-Anhänge, Read Receipts, E2E-Verschlüsselung, OS-Push-Notifications
## Abgeschlossen (2026-05-16) **Zyklen:** 1 Implementierungszyklus + 1 Review-Korrektur (N+1-Query) **Tests:** ✅ 234 Tests, 0 Fehler ### Implementierte Artefakte **Shared** - ✅ \MessageDto\: id, senderId, senderUsername, receiverId, body, sentAt, deliveredAt? - ✅ \UserListItemDto\: id, username **Server** - ✅ \Messages\-Tabelle: id, sender_id, receiver_id, body, sent_at, delivered_at (nullable) - ✅ \MessageRepository\: save, getUndelivered (JOIN), getConversation (JOIN), markDelivered - ✅ \POST /api/messages\, \GET /api/messages/{userId}\ - ✅ \GET /api/users\ (alle User außer eigenem Account) - ✅ WebSocket-Push bei neuem Message (\ otifyNewMessage\) - ✅ Unzugestellte Nachrichten bei Reconnect automatisch pushen - ✅ \LoginResponse\ um userId + username erweitert **App** - ✅ \MessageEntity\ + \MessageDao\ (Room, Migration 3→4) - ✅ \MessageRepositoryImpl\: Offline-First (isPending), drain bei WebSocket-Connect - ✅ \WebSocketEvent.NewMessage\ → automatisch in Room persistiert - ✅ \AUTH_USER_ID\ in SettingsKeys, bei Login gespeichert - ✅ \UserListScreen\ + \UserListViewModel\: User-Liste mit Tap-Navigation - ✅ \ChatScreen\ + \ChatViewModel\: WhatsApp-Style (eigene Nachrichten rechts, fremde links, Zeitstempel) - ✅ \MESSAGES\-Eintrag in Bottom-Navigation ### Nicht im Scope (wie definiert) - Gruppen-Chats, Bild-Anhänge, Read Receipts, E2E-Verschlüsselung, OS-Push-Notifications
Sign in to join this conversation.
No description provided.