This commit is contained in:
parent
34127cd14f
commit
9151aa7f04
|
@ -1726,14 +1726,8 @@ func (db sqlitePersistence) MarkAllRead(chatID string, clock uint64) (int64, int
|
||||||
|
|
||||||
_, err = tx.Exec(
|
_, err = tx.Exec(
|
||||||
`UPDATE chats
|
`UPDATE chats
|
||||||
SET unviewed_message_count =
|
SET unviewed_message_count = 0,
|
||||||
(SELECT COUNT(1)
|
unviewed_mentions_count = 0,
|
||||||
FROM user_messages
|
|
||||||
WHERE local_chat_id = ? AND seen = 0),
|
|
||||||
unviewed_mentions_count =
|
|
||||||
(SELECT COUNT(1)
|
|
||||||
FROM user_messages
|
|
||||||
WHERE local_chat_id = ? AND seen = 0 AND (mentioned or replied)),
|
|
||||||
highlight = 0
|
highlight = 0
|
||||||
WHERE id = ?`, chatID, chatID, chatID)
|
WHERE id = ?`, chatID, chatID, chatID)
|
||||||
|
|
||||||
|
|
|
@ -4857,7 +4857,7 @@ func (m *Messenger) markAllRead(chatID string, clock uint64, shouldBeSynced bool
|
||||||
return errors.New("chat not found")
|
return errors.New("chat not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
seen, mentioned, err := m.persistence.MarkAllRead(chatID, clock)
|
_, _, err := m.persistence.MarkAllRead(chatID, clock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -4872,17 +4872,8 @@ func (m *Messenger) markAllRead(chatID string, clock uint64, shouldBeSynced bool
|
||||||
chat.ReadMessagesAtClockValue = clock
|
chat.ReadMessagesAtClockValue = clock
|
||||||
chat.Highlight = false
|
chat.Highlight = false
|
||||||
|
|
||||||
if chat.UnviewedMessagesCount >= uint(seen) {
|
chat.UnviewedMessagesCount = 0
|
||||||
chat.UnviewedMessagesCount -= uint(seen)
|
chat.UnviewedMentionsCount = 0
|
||||||
} else {
|
|
||||||
chat.UnviewedMessagesCount = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
if chat.UnviewedMentionsCount >= uint(mentioned) {
|
|
||||||
chat.UnviewedMentionsCount -= uint(mentioned)
|
|
||||||
} else {
|
|
||||||
chat.UnviewedMentionsCount = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(samyoul) remove storing of an updated reference pointer?
|
// TODO(samyoul) remove storing of an updated reference pointer?
|
||||||
m.allChats.Store(chat.ID, chat)
|
m.allChats.Store(chat.ID, chat)
|
||||||
|
|
|
@ -477,6 +477,7 @@ func (m *Messenger) saveChat(chat *Chat) error {
|
||||||
chat.Alias = name
|
chat.Alias = name
|
||||||
chat.Identicon = identicon
|
chat.Identicon = identicon
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync chat if it's a new active public chat, but not a timeline chat
|
// Sync chat if it's a new active public chat, but not a timeline chat
|
||||||
if !ok && chat.Active && chat.Public() && !chat.ProfileUpdates() && !chat.Timeline() {
|
if !ok && chat.Active && chat.Public() && !chat.ProfileUpdates() && !chat.Timeline() {
|
||||||
|
|
||||||
|
|
|
@ -453,6 +453,68 @@ func (s *MessengerDeleteMessageSuite) TestDeleteMessageWithAMention() {
|
||||||
s.Require().Len(response.Chats(), 1)
|
s.Require().Len(response.Chats(), 1)
|
||||||
s.Require().Len(response.Messages(), 1)
|
s.Require().Len(response.Messages(), 1)
|
||||||
// Receiver (us) is no longer mentioned
|
// Receiver (us) is no longer mentioned
|
||||||
s.Require().Equal(int(response.Chats()[0].UnviewedMessagesCount), 0)
|
s.Require().Equal(int(state.Response.Chats()[0].UnviewedMessagesCount), 0)
|
||||||
s.Require().Equal(int(response.Chats()[0].UnviewedMentionsCount), 0)
|
s.Require().Equal(int(state.Response.Chats()[0].UnviewedMentionsCount), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test makes sure the UnviewMessageCount doesn't go below 0 in a very rare case where the Chat could be marked
|
||||||
|
// as read but the message still unseen (Seen == false)
|
||||||
|
func (s *MessengerDeleteMessageSuite) TestDeleteMessageAndChatIsAlreadyRead() {
|
||||||
|
theirMessenger := s.newMessenger()
|
||||||
|
_, err := theirMessenger.Start()
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
theirChat := CreateOneToOneChat("Their 1TO1", &s.privateKey.PublicKey, s.m.transport)
|
||||||
|
err = theirMessenger.SaveChat(theirChat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
ourChat := CreateOneToOneChat("Our 1TO1", &theirMessenger.identity.PublicKey, s.m.transport)
|
||||||
|
err = s.m.SaveChat(ourChat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
inputMessage := buildTestMessage(*theirChat)
|
||||||
|
sendResponse, err := theirMessenger.SendChatMessage(context.Background(), inputMessage)
|
||||||
|
s.NoError(err)
|
||||||
|
s.Require().Len(sendResponse.Messages(), 1)
|
||||||
|
|
||||||
|
response, err := WaitOnMessengerResponse(
|
||||||
|
s.m,
|
||||||
|
func(r *MessengerResponse) bool { return len(r.messages) == 1 },
|
||||||
|
"no messages",
|
||||||
|
)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(response.Chats(), 1)
|
||||||
|
s.Require().Equal(response.Chats()[0].UnviewedMessagesCount, uint(1))
|
||||||
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
|
||||||
|
// Force UnviewedMessagesCount to 0 to test if the uint validation is done correctly
|
||||||
|
ourChat.UnviewedMessagesCount = 0
|
||||||
|
err = s.m.saveChat(ourChat)
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
ogMessage := sendResponse.Messages()[0]
|
||||||
|
|
||||||
|
deleteMessage := DeleteMessage{
|
||||||
|
DeleteMessage: protobuf.DeleteMessage{
|
||||||
|
Clock: 2,
|
||||||
|
MessageType: protobuf.MessageType_ONE_TO_ONE,
|
||||||
|
MessageId: ogMessage.ID,
|
||||||
|
ChatId: theirChat.ID,
|
||||||
|
},
|
||||||
|
From: common.PubkeyToHex(&theirMessenger.identity.PublicKey),
|
||||||
|
}
|
||||||
|
|
||||||
|
state := &ReceivedMessageState{
|
||||||
|
Response: &MessengerResponse{},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle Delete first
|
||||||
|
err = s.m.HandleDeleteMessage(state, deleteMessage)
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(response.Chats(), 1)
|
||||||
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
// Receiver (us) no longer has unread messages and it's not negative
|
||||||
|
s.Require().Equal(0, int(state.Response.Chats()[0].UnviewedMessagesCount))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1632,8 +1632,10 @@ func (m *Messenger) HandleDeleteMessage(state *ReceivedMessageState, deleteMessa
|
||||||
// Reduce chat mention count and unread count if unread
|
// Reduce chat mention count and unread count if unread
|
||||||
if !messageToDelete.Seen && !unreadCountDecreased {
|
if !messageToDelete.Seen && !unreadCountDecreased {
|
||||||
unreadCountDecreased = true
|
unreadCountDecreased = true
|
||||||
chat.UnviewedMessagesCount--
|
if chat.UnviewedMessagesCount > 0 {
|
||||||
if messageToDelete.Mentioned || messageToDelete.Replied {
|
chat.UnviewedMessagesCount--
|
||||||
|
}
|
||||||
|
if chat.UnviewedMentionsCount > 0 && (messageToDelete.Mentioned || messageToDelete.Replied) {
|
||||||
chat.UnviewedMentionsCount--
|
chat.UnviewedMentionsCount--
|
||||||
}
|
}
|
||||||
err := m.saveChat(chat)
|
err := m.saveChat(chat)
|
||||||
|
|
|
@ -418,6 +418,9 @@ func (db sqlitePersistence) Chat(chatID string) (*Chat, error) {
|
||||||
imagePayload []byte
|
imagePayload []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var unviewedMessagesCount int
|
||||||
|
var unviewedMentionsCount int
|
||||||
|
|
||||||
err := db.db.QueryRow(`
|
err := db.db.QueryRow(`
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
|
@ -459,8 +462,8 @@ func (db sqlitePersistence) Chat(chatID string) (*Chat, error) {
|
||||||
&chat.Timestamp,
|
&chat.Timestamp,
|
||||||
&chat.ReadMessagesAtClockValue,
|
&chat.ReadMessagesAtClockValue,
|
||||||
&chat.DeletedAtClockValue,
|
&chat.DeletedAtClockValue,
|
||||||
&chat.UnviewedMessagesCount,
|
&unviewedMessagesCount,
|
||||||
&chat.UnviewedMentionsCount,
|
&unviewedMentionsCount,
|
||||||
&chat.LastClockValue,
|
&chat.LastClockValue,
|
||||||
&lastMessageBytes,
|
&lastMessageBytes,
|
||||||
&encodedMembers,
|
&encodedMembers,
|
||||||
|
@ -498,6 +501,18 @@ func (db sqlitePersistence) Chat(chatID string) (*Chat, error) {
|
||||||
if profile.Valid {
|
if profile.Valid {
|
||||||
chat.Profile = profile.String
|
chat.Profile = profile.String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set UnviewedCounts and make sure they are above 0
|
||||||
|
// Since Chat's UnviewedMessagesCount is uint and the SQL column is INT, it can create a discrepancy
|
||||||
|
if unviewedMessagesCount < 0 {
|
||||||
|
unviewedMessagesCount = 0
|
||||||
|
}
|
||||||
|
if unviewedMentionsCount < 0 {
|
||||||
|
unviewedMentionsCount = 0
|
||||||
|
}
|
||||||
|
chat.UnviewedMessagesCount = uint(unviewedMessagesCount)
|
||||||
|
chat.UnviewedMentionsCount = uint(unviewedMentionsCount)
|
||||||
|
|
||||||
// Restore members
|
// Restore members
|
||||||
membersDecoder := gob.NewDecoder(bytes.NewBuffer(encodedMembers))
|
membersDecoder := gob.NewDecoder(bytes.NewBuffer(encodedMembers))
|
||||||
err = membersDecoder.Decode(&chat.Members)
|
err = membersDecoder.Decode(&chat.Members)
|
||||||
|
|
Loading…
Reference in New Issue