diff --git a/cli/client.go b/cli/client.go index f3c5858..ce4de47 100644 --- a/cli/client.go +++ b/cli/client.go @@ -236,13 +236,6 @@ func (c *Client) onContactEvent(event *ricochet.ContactEvent) { } func (c *Client) onConversationEvent(event *ricochet.ConversationEvent) { - // XXX Ignoring updates, errors, etc - if event.Type != ricochet.ConversationEvent_RECEIVE && - event.Type != ricochet.ConversationEvent_SEND && - event.Type != ricochet.ConversationEvent_POPULATE { - return - } - message := event.Msg if event.Type == ricochet.ConversationEvent_POPULATE && message == nil { @@ -251,7 +244,8 @@ func (c *Client) onConversationEvent(event *ricochet.ConversationEvent) { return } - if message == nil || message.Recipient == nil || message.Sender == nil { + if message == nil || message.Recipient == nil || message.Sender == nil || + (message.Sender.IsSelf && message.Recipient.IsSelf) { log.Printf("Ignoring invalid conversation event: %v", event) return } @@ -269,8 +263,21 @@ func (c *Client) onConversationEvent(event *ricochet.ConversationEvent) { return } - remoteContact.Conversation.AddMessage(message, - event.Type == ricochet.ConversationEvent_POPULATE) + switch event.Type { + case ricochet.ConversationEvent_POPULATE: + fallthrough + case ricochet.ConversationEvent_RECEIVE: + fallthrough + case ricochet.ConversationEvent_SEND: + remoteContact.Conversation.AddMessage(message, + event.Type == ricochet.ConversationEvent_POPULATE) + + case ricochet.ConversationEvent_UPDATE: + remoteContact.Conversation.UpdateMessage(message) + + default: + log.Printf("Ignoring conversation event with unknown type: %v", event) + } } func (c *Client) NetworkControlStatus() ricochet.TorControlStatus { diff --git a/cli/conversation.go b/cli/conversation.go index e6b9ef0..c5a51ed 100644 --- a/cli/conversation.go +++ b/cli/conversation.go @@ -26,7 +26,8 @@ type Conversation struct { Client *Client Contact *Contact - messages []*ricochet.Message + messages []*ricochet.Message + numUnread int } // Send an outbound message to the contact and add that message into the @@ -62,6 +63,9 @@ func (c *Conversation) AddMessage(msg *ricochet.Message, populating bool) { } c.messages = append(c.messages, msg) + if msg.Status == ricochet.Message_UNREAD { + c.numUnread++ + } c.trimBacklog() if !populating { // XXX Need to do mark-as-read when displaying received messages in @@ -72,6 +76,31 @@ func (c *Conversation) AddMessage(msg *ricochet.Message, populating bool) { } } +func (c *Conversation) UpdateMessage(updatedMsg *ricochet.Message) { + if err := c.validateMessage(updatedMsg); err != nil { + log.Printf("Rejected conversation message update: %v", err) + return + } + + for i := len(c.messages) - 1; i >= 0; i-- { + msg := c.messages[i] + if msg.Sender.IsSelf != updatedMsg.Sender.IsSelf || + msg.Identifier != updatedMsg.Identifier { + continue + } + + if msg.Status == ricochet.Message_UNREAD && + updatedMsg.Status != ricochet.Message_UNREAD { + c.numUnread-- + } + + c.messages[i] = updatedMsg + return + } + + log.Printf("Ignoring message update for unknown message: %v", updatedMsg) +} + // XXX func (c *Conversation) AddStatusMessage(text string, backlog bool) { } @@ -141,6 +170,7 @@ func (c *Conversation) PrintContext() { func (c *Conversation) trimBacklog() { if len(c.messages) > backlogHardLimit { c.messages = c.messages[len(c.messages)-backlogHardLimit:] + c.recountUnread() } if len(c.messages) <= backlogSoftLimit { return @@ -230,3 +260,16 @@ func (c *Conversation) printMessage(msg *ricochet.Message) { fmt.Fprintf(ui.Input.Stdout(), "\r\x1b[31m( \x1b[39mNew message from \x1b[31m%s\x1b[39m -- \x1b[1m/%d\x1b[0m to view \x1b[31m)\x1b[39m\n", contact.Data.Nickname, contact.Data.Id) */ } + +func (c *Conversation) UnreadCount() int { + return c.numUnread +} + +func (c *Conversation) recountUnread() { + c.numUnread = 0 + for _, msg := range c.messages { + if msg.Status == ricochet.Message_UNREAD { + c.numUnread++ + } + } +}