Files
libredesk/internal/ws/models/models.go
Abhinav Raut 723c0e84ba fix notification and conversation read state
Opening a conversation used to mark it read even when the agent never scrolled to the new messages or the tab was in the background. Reply notifications in the bell also stayed unread after the agent read the reply.

Now the browser tells the server which message the agent saw. It only does this when the end of the thread is on screen and the tab has focus. The server moves the agent's last seen time forward to that message and never back.

A reply notification counts as read when the agent's last seen time is at or after the reply. "Mark as unread" marks the old reply notifications read first, so the bell stays the same.

Reply emails and pushes wait a little before sending. They are skipped if the agent already read the message or can no longer see the conversation.
2026-10-08 00:33:14 +05:30

55 lines
1.7 KiB
Go

package models
import "encoding/json"
// Action constants for WebSocket messages.
const (
MessageTypeMessageUpdate = "message_update"
MessageTypeConversationUpdate = "conversation_update"
MessageTypeNewMessage = "new_message"
MessageTypeNewConversation = "new_conversation"
MessageTypeNewNotification = "new_notification"
MessageTypeConversationRead = "conversation_read"
MessageTypeError = "error"
MessageTypeConversationSubscribe = "conversation_subscribe"
MessageTypeTyping = "typing"
MessageTypeListSubscribeReplace = "list_subscribe_replace"
MessageTypeAgentAvailability = "agent_availability_update"
)
// WSMessage represents a WS message.
type WSMessage struct {
MessageType int
Data []byte
}
// Message represents a WebSocket message to be sent.
type Message struct {
Type string `json:"type"`
Data interface{} `json:"data"`
}
// IncomingMessage is an inbound client frame with its payload kept raw for the per-type handlers.
type IncomingMessage struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
// BroadcastMessage represents a message to be pushed to users.
type BroadcastMessage struct {
Data []byte `json:"data"`
Users []int `json:"users"`
}
// ConversationSubscribe represents a conversation subscription message.
type ConversationSubscribe struct {
ConversationUUID string `json:"conversation_uuid"`
}
// TypingMessage represents a typing indicator message.
type TypingMessage struct {
ConversationUUID string `json:"conversation_uuid"`
IsTyping bool `json:"is_typing"`
IsPrivateMessage bool `json:"is_private_message"`
}