package main import ( "context" "net/http" "strings" ) func (s *Server) markChatConversationRead( ctx context.Context, conversationID string, userID string, ) error { _, err := s.db.Exec( ctx, ` INSERT INTO conversation_members ( conversation_id, user_id, last_read_at ) VALUES ($1, $2, now()) ON CONFLICT (conversation_id, user_id) DO UPDATE SET last_read_at = EXCLUDED.last_read_at `, conversationID, userID, ) return err } func (s *Server) getChatUnreadCount(ctx context.Context, userID string) (int, error) { var unreadCount int err := s.db.QueryRow( ctx, ` SELECT COUNT(*)::INT FROM messages m JOIN conversations c ON c.id = m.conversation_id LEFT JOIN conversation_members cm ON cm.conversation_id = c.id AND cm.user_id = $1 WHERE m.deleted_at IS NULL AND (m.expires_at IS NULL OR m.expires_at > now()) AND m.sender_id IS DISTINCT FROM $1::UUID AND m.created_at > COALESCE(cm.last_read_at, '-infinity'::TIMESTAMPTZ) AND cm.user_id IS NOT NULL `, userID, ).Scan(&unreadCount) return unreadCount, err } func (s *Server) handleGetChatUnreadCount(w http.ResponseWriter, r *http.Request) { user, ok := userFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "Unauthorized") return } if err := s.ensureTeamGroupConversations(r.Context()); err != nil { writeError(w, http.StatusInternalServerError, "Team-Gruppenchats konnten nicht vorbereitet werden") return } if err := s.ensureAllUserChannels(r.Context(), user.ID); err != nil { writeError(w, http.StatusInternalServerError, "Channels konnten nicht vorbereitet werden") return } unreadCount, err := s.getChatUnreadCount(r.Context(), user.ID) if err != nil { writeError(w, http.StatusInternalServerError, "Ungelesene Nachrichten konnten nicht geladen werden") return } writeJSON(w, http.StatusOK, map[string]any{ "unreadCount": unreadCount, }) } func (s *Server) handleMarkChatConversationRead(w http.ResponseWriter, r *http.Request) { user, ok := userFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "Unauthorized") return } conversationID := strings.TrimSpace(r.PathValue("id")) if !s.canAccessConversation(r.Context(), conversationID, user.ID) { writeError(w, http.StatusForbidden, "Kein Zugriff auf diesen Chat") return } if err := s.markChatConversationRead(r.Context(), conversationID, user.ID); err != nil { writeError(w, http.StatusInternalServerError, "Lesestatus konnte nicht gespeichert werden") return } unreadCount, err := s.getChatUnreadCount(r.Context(), user.ID) if err != nil { writeError(w, http.StatusInternalServerError, "Ungelesene Nachrichten konnten nicht geladen werden") return } writeJSON(w, http.StatusOK, map[string]any{ "unreadCount": unreadCount, }) }