diff --git a/chat/chat.go b/chat/chat.go index 3e71670f..f82f98af 100644 --- a/chat/chat.go +++ b/chat/chat.go @@ -105,6 +105,39 @@ type Client struct { var rooms = make(map[string]*Room) var roomsMutex sync.RWMutex +// ChatMessage represents a direct message between users +type ChatMessage struct { + ID string `json:"id"` + From string `json:"from"` // Sender username + FromID string `json:"from_id"` // Sender account ID + To string `json:"to"` // Recipient username + ToID string `json:"to_id"` // Recipient account ID + Body string `json:"body"` + Read bool `json:"read"` + ReplyTo string `json:"reply_to"` // ID of message this is replying to + ThreadID string `json:"thread_id"` // Root message ID for O(1) thread grouping + CreatedAt time.Time `json:"created_at"` +} + +// ChatThread represents a conversation thread +type ChatThread struct { + Root *ChatMessage + Messages []*ChatMessage + Latest *ChatMessage + HasUnread bool +} + +// ChatInbox organizes messages by thread for a user +type ChatInbox struct { + Threads map[string]*ChatThread // threadID -> Thread + UnreadCount int // Cached unread message count +} + +// stored direct messages +var chatMessages []*ChatMessage +var chatInboxes map[string]*ChatInbox +var chatMessagesMutex sync.RWMutex + // saveRoomMessages persists room messages to disk func saveRoomMessages(roomID string, messages []RoomMessage) { filename := "room_" + strings.ReplaceAll(roomID, "/", "_") + ".json" @@ -1023,6 +1056,9 @@ func Load() { } } + // Load chat messages + loadChatMessages() + // Subscribe to summary generation requests summaryRequestSub := data.Subscribe(data.EventGenerateSummary) go func() { @@ -1234,6 +1270,14 @@ func generateSummaries() { } func Handler(w http.ResponseWriter, r *http.Request) { + // Check mode parameter - "messages" for direct messaging, default is AI chat + mode := r.URL.Query().Get("mode") + + if mode == "messages" { + handleMessagesMode(w, r) + return + } + // Check if this is a room-based chat (e.g., /chat?id=post_123) roomID := r.URL.Query().Get("id") @@ -1348,6 +1392,13 @@ func handleGetChat(w http.ResponseWriter, r *http.Request, roomID string) { roomJSON, _ := json.Marshal(roomData) tmpl := app.RenderHTMLForRequest("Chat", "Chat with AI", fmt.Sprintf(Template, topicTabs), r) + + // Add a link to messages mode + messagesLink := `
💬 New: Direct Messaging - Send messages to other users or chat with @micro (AI assistant)
+