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
|
||||
}
|
||||
|
||||
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 {
|
||||
_, err := db.db.Exec(`
|
||||
UPDATE user_messages
|
||||
|
|
|
@ -4142,6 +4142,49 @@ func (m *Messenger) DeleteMessagesByChatID(id string) error {
|
|||
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`.
|
||||
// It returns the number of affected messages or error. If there is an error,
|
||||
// the number of affected messages is always zero.
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
"strings"
|
||||
|
@ -2474,7 +2474,7 @@ func buildImageWithAlbumIDMessage(chat Chat, albumID string) (*common.Message, e
|
|||
}
|
||||
defer file.Close()
|
||||
|
||||
payload, err := ioutil.ReadAll(file)
|
||||
payload, err := io.ReadAll(file)
|
||||
if err != 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
|
||||
}
|
||||
|
||||
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) {
|
||||
return api.service.messenger.MarkAllRead(ctx, chatID)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue