110 lines
2.8 KiB
Go
110 lines
2.8 KiB
Go
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.message_type <> 'system'
|
|
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,
|
|
})
|
|
}
|