feature(@desktop/chat) Enhance message context menu with mark as unread (#4382)
fixes #10329 linked with PR #12879 - Adds capacity to mark a message as unread - Adds capacity to mark a message with mention as unread - Adds persistence to the marking of the message (change can be seen at after reboot) - Adds marking in right click contextual menu
This commit is contained in:
parent
be8568e174
commit
0f98a1294c
|
@ -1891,6 +1891,99 @@ func (db sqlitePersistence) MarkMessagesSeen(chatID string, ids []string) (uint6
|
||||||
return countWithMentions + countNoMentions, countWithMentions, err
|
return countWithMentions + countNoMentions, countWithMentions, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db sqlitePersistence) GetMessageIdsWithGreaterTimestamp(chatID string, messageID string) ([]string, error) {
|
||||||
|
var err error
|
||||||
|
var rows *sql.Rows
|
||||||
|
query := "SELECT id FROM user_messages WHERE local_chat_id = ? AND timestamp >= (SELECT timestamp FROM user_messages WHERE id = ?)"
|
||||||
|
|
||||||
|
rows, err = db.db.Query(query, chatID, messageID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var ids []string
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var messageID string
|
||||||
|
err = rows.Scan(&messageID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ids = append(ids, messageID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db sqlitePersistence) MarkMessageAsUnread(chatID string, messageID string) (uint64, uint64, error) {
|
||||||
|
tx, err := db.db.BeginTx(context.Background(), &sql.TxOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
err = tx.Commit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// don't shadow original error
|
||||||
|
_ = tx.Rollback()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// TODO : Reduce number of queries for getting (total unread messages, total messages with mention)
|
||||||
|
// The function expected result is a pair (total unread messages, total messages with mention)
|
||||||
|
// Currently a 2 step operation is needed to obtain this pair
|
||||||
|
_, err = tx.Exec(`UPDATE user_messages SET seen = 1 WHERE local_chat_id = ? AND NOT(seen)`, chatID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(
|
||||||
|
`UPDATE user_messages
|
||||||
|
SET seen = 0
|
||||||
|
WHERE local_chat_id = ?
|
||||||
|
AND seen = 1
|
||||||
|
AND (mentioned OR replied)
|
||||||
|
AND timestamp >= (SELECT timestamp FROM user_messages WHERE id = ?)`, chatID, messageID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var countWithMentions uint64
|
||||||
|
row := tx.QueryRow("SELECT changes();")
|
||||||
|
if err := row.Scan(&countWithMentions); err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(
|
||||||
|
`UPDATE user_messages
|
||||||
|
SET seen = 0
|
||||||
|
WHERE local_chat_id = ?
|
||||||
|
AND seen = 1
|
||||||
|
AND NOT(mentioned OR replied)
|
||||||
|
AND timestamp >= (SELECT timestamp FROM user_messages WHERE id = ?)`, chatID, messageID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var countNoMentions uint64
|
||||||
|
row = tx.QueryRow("SELECT changes();")
|
||||||
|
if err := row.Scan(&countNoMentions); err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
count := countWithMentions + countNoMentions
|
||||||
|
|
||||||
|
_, err = tx.Exec(
|
||||||
|
`UPDATE chats
|
||||||
|
SET unviewed_message_count = ?, unviewed_mentions_count = ?,
|
||||||
|
highlight = 0
|
||||||
|
WHERE id = ?`, count, countWithMentions, chatID)
|
||||||
|
|
||||||
|
return count, countWithMentions, err
|
||||||
|
}
|
||||||
|
|
||||||
func (db sqlitePersistence) UpdateMessageOutgoingStatus(id string, newOutgoingStatus string) error {
|
func (db sqlitePersistence) UpdateMessageOutgoingStatus(id string, newOutgoingStatus string) error {
|
||||||
_, err := db.db.Exec(`
|
_, err := db.db.Exec(`
|
||||||
UPDATE user_messages
|
UPDATE user_messages
|
||||||
|
|
|
@ -4142,6 +4142,49 @@ func (m *Messenger) DeleteMessagesByChatID(id string) error {
|
||||||
return m.persistence.DeleteMessagesByChatID(id)
|
return m.persistence.DeleteMessagesByChatID(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Messenger) MarkMessageAsUnreadImpl(chatID string, messageID string) (uint64, uint64, error) {
|
||||||
|
count, countWithMentions, err := m.persistence.MarkMessageAsUnread(chatID, messageID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
chat, err := m.persistence.Chat(chatID)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
m.allChats.Store(chatID, chat)
|
||||||
|
return count, countWithMentions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Messenger) MarkMessageAsUnread(chatID string, messageID string) (uint64, uint64, []*ActivityCenterNotification, error) {
|
||||||
|
count, countWithMentions, err := m.MarkMessageAsUnreadImpl(chatID, messageID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ids, err := m.persistence.GetMessageIdsWithGreaterTimestamp(chatID, messageID)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
hexBytesIds := []types.HexBytes{}
|
||||||
|
for _, id := range ids {
|
||||||
|
hexBytesIds = append(hexBytesIds, types.FromHex(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedAt := m.GetCurrentTimeInMillis()
|
||||||
|
notifications, err := m.persistence.MarkActivityCenterNotificationsUnread(hexBytesIds, updatedAt)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, countWithMentions, notifications, nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarkMessagesSeen marks messages with `ids` as seen in the chat `chatID`.
|
// MarkMessagesSeen marks messages with `ids` as seen in the chat `chatID`.
|
||||||
// It returns the number of affected messages or error. If there is an error,
|
// It returns the number of affected messages or error. If there is an error,
|
||||||
// the number of affected messages is always zero.
|
// the number of affected messages is always zero.
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -2474,7 +2474,7 @@ func buildImageWithAlbumIDMessage(chat Chat, albumID string) (*common.Message, e
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
payload, err := ioutil.ReadAll(file)
|
payload, err := io.ReadAll(file)
|
||||||
if err != err {
|
if err != err {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,360 @@
|
||||||
|
package protocol
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
_ "github.com/mutecomm/go-sqlcipher/v4" // require go-sqlcipher that overrides default implementation
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/protocol/common"
|
||||||
|
"github.com/status-im/status-go/protocol/protobuf"
|
||||||
|
"github.com/status-im/status-go/protocol/requests"
|
||||||
|
"github.com/status-im/status-go/protocol/tt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *MessengerSuite) checkMessageSeen(messageID string, expectedSeen bool) {
|
||||||
|
message, err := s.m.MessageByID(messageID)
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(expectedSeen, message.Seen)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MessengerSuite) retrieveAllWithRetry(errorMessage string) (*MessengerResponse, error) {
|
||||||
|
var response *MessengerResponse
|
||||||
|
var err error
|
||||||
|
|
||||||
|
retryFunc := func() error {
|
||||||
|
response, err = s.m.RetrieveAll()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(response.messages) == 0 {
|
||||||
|
return errors.New(errorMessage)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tt.RetryWithBackOff(retryFunc)
|
||||||
|
return response, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageListContainsSingleMessage() {
|
||||||
|
chat := CreatePublicChat("test-chat-1", s.m.transport)
|
||||||
|
|
||||||
|
chat.UnviewedMessagesCount = 2
|
||||||
|
chat.UnviewedMentionsCount = 2
|
||||||
|
chat.Highlight = true
|
||||||
|
|
||||||
|
err := s.m.SaveChat(chat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
inputMessage1 := buildTestMessage(*chat)
|
||||||
|
inputMessage1.ID = "1"
|
||||||
|
inputMessage1.Seen = true
|
||||||
|
inputMessage1.Mentioned = true
|
||||||
|
|
||||||
|
err = s.m.SaveMessages([]*common.Message{inputMessage1})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
_, err = s.m.MarkAllRead(context.Background(), chat.ID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
chats := s.m.allChats
|
||||||
|
|
||||||
|
actualChat, ok := chats.Load(chat.ID)
|
||||||
|
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
|
||||||
|
s.Require().False(actualChat.Highlight)
|
||||||
|
s.checkMessageSeen(inputMessage1.ID, true)
|
||||||
|
|
||||||
|
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage1.ID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(uint64(1), count)
|
||||||
|
s.Require().Equal(uint64(1), countWithMentions)
|
||||||
|
s.Require().Len(notifications, 0)
|
||||||
|
|
||||||
|
chats = s.m.allChats
|
||||||
|
|
||||||
|
actualChat, ok = chats.Load(chat.ID)
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint(1), actualChat.UnviewedMentionsCount)
|
||||||
|
s.Require().False(actualChat.Highlight)
|
||||||
|
s.checkMessageSeen(inputMessage1.ID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageListContainsSeveralMessages() {
|
||||||
|
chat := CreatePublicChat("test-chat-2", s.m.transport)
|
||||||
|
|
||||||
|
chat.UnviewedMessagesCount = 0
|
||||||
|
chat.UnviewedMentionsCount = 0
|
||||||
|
chat.Highlight = true
|
||||||
|
|
||||||
|
err := s.m.SaveChat(chat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
inputMessage1 := buildTestMessage(*chat)
|
||||||
|
inputMessage1.ID = "1"
|
||||||
|
inputMessage1.Seen = true
|
||||||
|
inputMessage1.Mentioned = true
|
||||||
|
inputMessage1.Timestamp = 1
|
||||||
|
|
||||||
|
inputMessage2 := buildTestMessage(*chat)
|
||||||
|
inputMessage2.ID = "2"
|
||||||
|
inputMessage2.Seen = true
|
||||||
|
inputMessage2.Mentioned = false
|
||||||
|
inputMessage2.Timestamp = 2
|
||||||
|
|
||||||
|
inputMessage3 := buildTestMessage(*chat)
|
||||||
|
inputMessage3.ID = "3"
|
||||||
|
inputMessage3.Seen = true
|
||||||
|
inputMessage3.Mentioned = false
|
||||||
|
inputMessage3.Timestamp = 3
|
||||||
|
|
||||||
|
err = s.m.SaveMessages([]*common.Message{
|
||||||
|
inputMessage1,
|
||||||
|
inputMessage2,
|
||||||
|
inputMessage3,
|
||||||
|
})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
_, err = s.m.MarkAllRead(context.Background(), chat.ID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
chats := s.m.allChats
|
||||||
|
actualChat, ok := chats.Load(chat.ID)
|
||||||
|
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
|
||||||
|
s.Require().False(actualChat.Highlight)
|
||||||
|
s.checkMessageSeen(inputMessage1.ID, true)
|
||||||
|
s.checkMessageSeen(inputMessage2.ID, true)
|
||||||
|
s.checkMessageSeen(inputMessage3.ID, true)
|
||||||
|
|
||||||
|
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage2.ID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
// count is 2 because the messages are layout the following way :
|
||||||
|
//
|
||||||
|
// inputMessage1 read <-- mentioned
|
||||||
|
// ----------------------------- <-- marker
|
||||||
|
// inputMessage2 unread
|
||||||
|
// inputMessage3 unread
|
||||||
|
//
|
||||||
|
// And the inputMessage3 has greater timestamp than inputMessage2
|
||||||
|
// Similarly, the mentioned message is inputMessage1, therefore the
|
||||||
|
// countWithMentions is 0
|
||||||
|
s.Require().Equal(uint64(2), count)
|
||||||
|
s.Require().Equal(uint64(0), countWithMentions)
|
||||||
|
s.Require().Len(notifications, 0)
|
||||||
|
|
||||||
|
chats = s.m.allChats
|
||||||
|
actualChat, ok = chats.Load(chat.ID)
|
||||||
|
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(uint(2), actualChat.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
|
||||||
|
s.Require().False(actualChat.Highlight)
|
||||||
|
s.checkMessageSeen(inputMessage1.ID, true)
|
||||||
|
s.checkMessageSeen(inputMessage2.ID, false)
|
||||||
|
s.checkMessageSeen(inputMessage3.ID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MessengerSuite) TestMarkMessageAsUnreadWhenMessageIsAlreadyInUnreadState() {
|
||||||
|
chat := CreatePublicChat("test-chat-3", s.m.transport)
|
||||||
|
|
||||||
|
chat.UnviewedMessagesCount = 1
|
||||||
|
chat.UnviewedMentionsCount = 0
|
||||||
|
chat.Highlight = true
|
||||||
|
|
||||||
|
err := s.m.SaveChat(chat)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
inputMessage1 := buildTestMessage(*chat)
|
||||||
|
inputMessage1.ID = "1"
|
||||||
|
inputMessage1.Seen = false
|
||||||
|
inputMessage1.Mentioned = false
|
||||||
|
|
||||||
|
err = s.m.SaveMessages([]*common.Message{inputMessage1})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
chats := s.m.allChats
|
||||||
|
actualChat, ok := chats.Load(chat.ID)
|
||||||
|
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
|
||||||
|
s.Require().True(actualChat.Highlight)
|
||||||
|
s.checkMessageSeen(inputMessage1.ID, false)
|
||||||
|
|
||||||
|
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(chat.ID, inputMessage1.ID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(uint64(1), count)
|
||||||
|
s.Require().Equal(uint64(0), countWithMentions)
|
||||||
|
s.Require().Len(notifications, 0)
|
||||||
|
|
||||||
|
chats = s.m.allChats
|
||||||
|
actualChat, ok = chats.Load(chat.ID)
|
||||||
|
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
|
||||||
|
s.Require().False(actualChat.Highlight)
|
||||||
|
s.checkMessageSeen(inputMessage1.ID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MessengerSuite) TestMarkMessageAsUnreadInOneChatDoesNotImpactOtherChats() {
|
||||||
|
chat1 := CreatePublicChat("test-chat-1", s.m.transport)
|
||||||
|
err := s.m.SaveChat(chat1)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
chat2 := CreatePublicChat("test-chat-2", s.m.transport)
|
||||||
|
err = s.m.SaveChat(chat2)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
chat1.UnviewedMessagesCount = 2
|
||||||
|
chat1.UnviewedMentionsCount = 0
|
||||||
|
chat1.Highlight = true
|
||||||
|
|
||||||
|
inputMessage1 := buildTestMessage(*chat1)
|
||||||
|
inputMessage1.ID = "1"
|
||||||
|
inputMessage1.Seen = true
|
||||||
|
inputMessage1.Mentioned = false
|
||||||
|
|
||||||
|
inputMessage2 := buildTestMessage(*chat1)
|
||||||
|
inputMessage2.ID = "2"
|
||||||
|
inputMessage2.Seen = true
|
||||||
|
inputMessage2.Mentioned = false
|
||||||
|
|
||||||
|
err = s.m.SaveMessages([]*common.Message{inputMessage1, inputMessage2})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
chat2.UnviewedMessagesCount = 1
|
||||||
|
chat2.UnviewedMentionsCount = 0
|
||||||
|
chat2.Highlight = true
|
||||||
|
|
||||||
|
inputMessage3 := buildTestMessage(*chat2)
|
||||||
|
inputMessage3.ID = "3"
|
||||||
|
inputMessage3.Seen = false
|
||||||
|
inputMessage3.Mentioned = false
|
||||||
|
|
||||||
|
err = s.m.SaveMessages([]*common.Message{inputMessage3})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
_, err = s.m.MarkAllRead(context.Background(), chat1.ID)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.checkMessageSeen(inputMessage1.ID, true)
|
||||||
|
s.checkMessageSeen(inputMessage2.ID, true)
|
||||||
|
|
||||||
|
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(chat1.ID, inputMessage1.ID)
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(uint(1), chat2.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint64(2), count)
|
||||||
|
s.Require().Equal(uint64(0), countWithMentions)
|
||||||
|
s.Require().Len(notifications, 0)
|
||||||
|
|
||||||
|
chats := s.m.allChats
|
||||||
|
actualChat, ok := chats.Load(chat1.ID)
|
||||||
|
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(uint(2), actualChat.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
|
||||||
|
s.Require().False(actualChat.Highlight)
|
||||||
|
s.checkMessageSeen(inputMessage1.ID, false)
|
||||||
|
s.checkMessageSeen(inputMessage2.ID, false)
|
||||||
|
|
||||||
|
actualChat, ok = chats.Load(chat2.ID)
|
||||||
|
s.Require().True(ok)
|
||||||
|
s.Require().Equal(uint(1), actualChat.UnviewedMessagesCount)
|
||||||
|
s.Require().Equal(uint(0), actualChat.UnviewedMentionsCount)
|
||||||
|
s.Require().True(actualChat.Highlight)
|
||||||
|
|
||||||
|
s.checkMessageSeen(inputMessage3.ID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *MessengerSuite) TestMarkMessageWithNotificationAsUnreadInCommunityChatSetsNotificationAsUnread() {
|
||||||
|
other := s.newMessenger()
|
||||||
|
|
||||||
|
description := &requests.CreateCommunity{
|
||||||
|
Membership: protobuf.CommunityPermissions_AUTO_ACCEPT,
|
||||||
|
Name: "status",
|
||||||
|
Color: "#ffffff",
|
||||||
|
Description: "This is just a test description for the community",
|
||||||
|
}
|
||||||
|
|
||||||
|
inviteMessage := "You are invited to community testing message"
|
||||||
|
|
||||||
|
response, err := other.CreateCommunity(description, true)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().NotNil(response)
|
||||||
|
s.Require().Len(response.Communities(), 1)
|
||||||
|
|
||||||
|
community := response.Communities()[0]
|
||||||
|
communityChat := response.Chats()[0]
|
||||||
|
|
||||||
|
_, err = community.AddMember(&s.m.identity.PublicKey, []protobuf.CommunityMember_Roles{})
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
err = other.communitiesManager.SaveCommunity(community)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
|
||||||
|
response, err = other.ShareCommunity(
|
||||||
|
&requests.ShareCommunity{
|
||||||
|
CommunityID: community.ID(),
|
||||||
|
Users: []types.HexBytes{common.PubkeyToHexBytes(&s.m.identity.PublicKey)},
|
||||||
|
InviteMessage: inviteMessage,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().NotNil(response)
|
||||||
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
|
||||||
|
response, err = s.retrieveAllWithRetry("community link not received")
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
|
||||||
|
message := response.Messages()[0]
|
||||||
|
s.Require().Equal(community.IDString(), message.CommunityID)
|
||||||
|
s.Require().Equal(inviteMessage, message.Text)
|
||||||
|
|
||||||
|
communityInResponse := response.Communities()[0]
|
||||||
|
s.Require().Equal(community.ID(), communityInResponse.ID())
|
||||||
|
s.Require().True(communityInResponse.Joined())
|
||||||
|
|
||||||
|
inputMessage1 := buildTestMessage(*communityChat)
|
||||||
|
inputMessage1.ChatId = communityChat.ID
|
||||||
|
inputMessage1.ContentType = protobuf.ChatMessage_TEXT_PLAIN
|
||||||
|
inputMessage1.Text = "Hello @" + common.EveryoneMentionTag + " !"
|
||||||
|
|
||||||
|
sendResponse, err := other.SendChatMessage(context.Background(), inputMessage1)
|
||||||
|
s.NoError(err)
|
||||||
|
s.Require().Len(sendResponse.Messages(), 1)
|
||||||
|
|
||||||
|
response, err = s.retrieveAllWithRetry("message from other chatter not received")
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(response.Chats(), 1)
|
||||||
|
s.Require().Len(response.Messages(), 1)
|
||||||
|
s.Require().Len(response.ActivityCenterNotifications(), 1)
|
||||||
|
s.Require().False(response.ActivityCenterNotifications()[0].Read)
|
||||||
|
|
||||||
|
response, err = s.m.MarkAllRead(context.Background(), communityChat.ID)
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Len(response.ActivityCenterNotifications(), 1)
|
||||||
|
s.Require().True(response.ActivityCenterNotifications()[0].Read)
|
||||||
|
|
||||||
|
count, countWithMentions, notifications, err := s.m.MarkMessageAsUnread(communityChat.ID, inputMessage1.ID)
|
||||||
|
|
||||||
|
s.Require().NoError(err)
|
||||||
|
s.Require().Equal(count, uint64(1))
|
||||||
|
s.Require().Equal(countWithMentions, uint64(1))
|
||||||
|
s.Require().Len(notifications, 1)
|
||||||
|
s.Require().False(notifications[0].Read)
|
||||||
|
}
|
|
@ -811,6 +811,20 @@ func (api *PublicAPI) MarkMessagesSeen(chatID string, ids []string) (*MarkMessag
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (api *PublicAPI) MarkMessageAsUnread(chatID string, messageID string) (*MarkMessageSeenResponse, error) {
|
||||||
|
count, withMentions, notifications, err := api.service.messenger.MarkMessageAsUnread(chatID, messageID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response := &MarkMessageSeenResponse{
|
||||||
|
Count: count,
|
||||||
|
CountWithMentions: withMentions,
|
||||||
|
ActivityCenterNotifications: notifications,
|
||||||
|
}
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (api *PublicAPI) MarkAllRead(ctx context.Context, chatID string) (*protocol.MessengerResponse, error) {
|
func (api *PublicAPI) MarkAllRead(ctx context.Context, chatID string) (*protocol.MessengerResponse, error) {
|
||||||
return api.service.messenger.MarkAllRead(ctx, chatID)
|
return api.service.messenger.MarkAllRead(ctx, chatID)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue