feat(edit-message): Edit image messages (#3393)
* feat(edit-message): Edit image messages * feat(edit-message): Adds tests for edit image messages text * chore(messenger_messages): Replace ErrChatNotFound duplications
This commit is contained in:
parent
213dc463bc
commit
2950d37e43
|
@ -6293,20 +6293,21 @@ func (m *Messenger) GetMentionsManager() *MentionManager {
|
|||
return m.mentionsManager
|
||||
}
|
||||
|
||||
func (m *Messenger) getMessagesToDelete(message *common.Message, chatID string) ([]*common.Message, error) {
|
||||
var messagesToDelete []*common.Message
|
||||
func (m *Messenger) getConnectedMessages(message *common.Message, chatID string) ([]*common.Message, error) {
|
||||
var connectedMessages []*common.Message
|
||||
// In case of Image messages, we need to delete all the images in the album
|
||||
if message.ContentType == protobuf.ChatMessage_IMAGE {
|
||||
image := message.GetImage()
|
||||
messagesInTheAlbum, err := m.persistence.albumMessages(chatID, image.GetAlbumId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if image != nil && image.AlbumId != "" {
|
||||
messagesInTheAlbum, err := m.persistence.albumMessages(chatID, image.GetAlbumId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
connectedMessages = append(connectedMessages, messagesInTheAlbum...)
|
||||
return connectedMessages, nil
|
||||
}
|
||||
messagesToDelete = append(messagesToDelete, messagesInTheAlbum...)
|
||||
} else {
|
||||
messagesToDelete = append(messagesToDelete, message)
|
||||
}
|
||||
return messagesToDelete, nil
|
||||
return append(connectedMessages, message), nil
|
||||
}
|
||||
|
||||
func (m *Messenger) withChatClock(callback func(string, uint64) error) error {
|
||||
|
|
|
@ -104,7 +104,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteMessage() {
|
|||
// Main instance user attempts to delete the message it received from theirMessenger
|
||||
_, err = s.m.DeleteMessageAndSend(context.Background(), ogMessage.ID)
|
||||
|
||||
s.Require().ErrorContains(err, "Chat not found")
|
||||
s.Require().ErrorContains(err, "can't find chat")
|
||||
}
|
||||
|
||||
func (s *MessengerDeleteMessageSuite) TestDeleteMessagePreviousLastMessage() {
|
||||
|
@ -309,7 +309,7 @@ func (s *MessengerDeleteMessageSuite) TestDeleteImageMessage() {
|
|||
// Main instance user attempts to delete the message it received from theirMessenger
|
||||
_, err = theirMessenger.DeleteMessageAndSend(context.Background(), firstMessageID)
|
||||
|
||||
s.Require().ErrorContains(err, "Chat not found")
|
||||
s.Require().ErrorContains(err, "can't find chat")
|
||||
}
|
||||
|
||||
func (s *MessengerDeleteMessageSuite) TestDeleteImageMessageFirstThenMessage() {
|
||||
|
|
|
@ -1592,7 +1592,7 @@ func (m *Messenger) HandleDeleteMessage(state *ReceivedMessageState, deleteMessa
|
|||
}
|
||||
}
|
||||
|
||||
messagesToDelete, err := m.getMessagesToDelete(originalMessage, deleteMessage.ChatId)
|
||||
messagesToDelete, err := m.getConnectedMessages(originalMessage, deleteMessage.ChatId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1674,7 +1674,7 @@ func (m *Messenger) HandleDeleteForMeMessage(state *ReceivedMessageState, delete
|
|||
return errors.New("chat not found")
|
||||
}
|
||||
|
||||
messagesToDelete, err := m.getMessagesToDelete(originalMessage, deleteForMeMessage.LocalChatID)
|
||||
messagesToDelete, err := m.getConnectedMessages(originalMessage, deleteForMeMessage.LocalChatID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -33,66 +33,74 @@ func (m *Messenger) EditMessage(ctx context.Context, request *requests.EditMessa
|
|||
return nil, ErrInvalidEditOrDeleteAuthor
|
||||
}
|
||||
|
||||
if message.ContentType != protobuf.ChatMessage_TEXT_PLAIN && message.ContentType != protobuf.ChatMessage_EMOJI {
|
||||
if message.ContentType != protobuf.ChatMessage_TEXT_PLAIN && message.ContentType != protobuf.ChatMessage_EMOJI && message.ContentType != protobuf.ChatMessage_IMAGE {
|
||||
return nil, ErrInvalidEditContentType
|
||||
}
|
||||
|
||||
// A valid added chat is required.
|
||||
chat, ok := m.allChats.Load(message.ChatId)
|
||||
if !ok {
|
||||
return nil, errors.New("Chat not found")
|
||||
return nil, ErrChatNotFound
|
||||
}
|
||||
|
||||
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
|
||||
|
||||
editMessage := &EditMessage{}
|
||||
|
||||
editMessage.Text = request.Text
|
||||
editMessage.ContentType = request.ContentType
|
||||
editMessage.ChatId = message.ChatId
|
||||
editMessage.MessageId = request.ID.String()
|
||||
editMessage.Clock = clock
|
||||
|
||||
err = m.applyEditMessage(&editMessage.EditMessage, message)
|
||||
messages, err := m.getConnectedMessages(message, message.LocalChatID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encodedMessage, err := m.encodeChatEntity(chat, editMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawMessage := common.RawMessage{
|
||||
LocalChatID: chat.ID,
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_EDIT_MESSAGE,
|
||||
SkipGroupMessageWrap: true,
|
||||
ResendAutomatically: true,
|
||||
}
|
||||
_, err = m.dispatchMessage(ctx, rawMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if chat.LastMessage != nil && chat.LastMessage.ID == message.ID {
|
||||
chat.LastMessage = message
|
||||
err := m.saveChat(chat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
response := &MessengerResponse{}
|
||||
|
||||
for _, message := range messages {
|
||||
|
||||
clock, _ := chat.NextClockAndTimestamp(m.getTimesource())
|
||||
|
||||
editMessage := &EditMessage{}
|
||||
|
||||
editMessage.Text = request.Text
|
||||
editMessage.ContentType = request.ContentType
|
||||
editMessage.ChatId = message.ChatId
|
||||
editMessage.MessageId = message.ID
|
||||
editMessage.Clock = clock
|
||||
|
||||
err = m.applyEditMessage(&editMessage.EditMessage, message)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encodedMessage, err := m.encodeChatEntity(chat, editMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rawMessage := common.RawMessage{
|
||||
LocalChatID: chat.ID,
|
||||
Payload: encodedMessage,
|
||||
MessageType: protobuf.ApplicationMetadataMessage_EDIT_MESSAGE,
|
||||
SkipGroupMessageWrap: true,
|
||||
ResendAutomatically: true,
|
||||
}
|
||||
_, err = m.dispatchMessage(ctx, rawMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if chat.LastMessage != nil && chat.LastMessage.ID == message.ID {
|
||||
chat.LastMessage = message
|
||||
err := m.saveChat(chat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
response.AddMessage(message)
|
||||
}
|
||||
|
||||
// pull updated messages
|
||||
updatedMessages, err := m.persistence.MessagesByResponseTo(request.ID.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
response.AddMessages(updatedMessages)
|
||||
|
||||
response.AddMessage(message)
|
||||
response.AddChat(chat)
|
||||
|
||||
return response, nil
|
||||
|
@ -129,7 +137,7 @@ func (m *Messenger) DeleteMessageAndSend(ctx context.Context, messageID string)
|
|||
// A valid added chat is required.
|
||||
chat, ok := m.allChats.Load(message.ChatId)
|
||||
if !ok {
|
||||
return nil, errors.New("Chat not found")
|
||||
return nil, ErrChatNotFound
|
||||
}
|
||||
|
||||
var canDeleteMessageForEveryone = false
|
||||
|
@ -165,7 +173,7 @@ func (m *Messenger) DeleteMessageAndSend(ctx context.Context, messageID string)
|
|||
return nil, ErrInvalidDeleteTypeAuthor
|
||||
}
|
||||
|
||||
messagesToDelete, err := m.getMessagesToDelete(message, message.ChatId)
|
||||
messagesToDelete, err := m.getConnectedMessages(message, message.ChatId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -235,7 +243,7 @@ func (m *Messenger) DeleteMessageForMeAndSync(ctx context.Context, chatID string
|
|||
// A valid added chat is required.
|
||||
chat, ok := m.allChats.Load(chatID)
|
||||
if !ok {
|
||||
return nil, errors.New("Chat not found")
|
||||
return nil, ErrChatNotFound
|
||||
}
|
||||
|
||||
// Only certain types of messages can be deleted
|
||||
|
@ -247,7 +255,7 @@ func (m *Messenger) DeleteMessageForMeAndSync(ctx context.Context, chatID string
|
|||
return nil, ErrInvalidDeleteTypeAuthor
|
||||
}
|
||||
|
||||
messagesToDelete, err := m.getMessagesToDelete(message, message.ChatId)
|
||||
messagesToDelete, err := m.getConnectedMessages(message, message.ChatId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ import (
|
|||
"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/requests"
|
||||
"github.com/status-im/status-go/protocol/tt"
|
||||
"github.com/status-im/status-go/waku"
|
||||
)
|
||||
|
@ -172,3 +172,85 @@ func (s *MessengerSendImagesAlbumSuite) TestAlbumImageMessagesWithMentionSend()
|
|||
|
||||
s.Require().Equal(uint(1), response.Chats()[0].UnviewedMessagesCount, "Just one unread message")
|
||||
}
|
||||
|
||||
func (s *MessengerSendImagesAlbumSuite) TestAlbumImageEditText() {
|
||||
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)
|
||||
|
||||
const messageCount = 3
|
||||
var album []*common.Message
|
||||
|
||||
for i := 0; i < messageCount; i++ {
|
||||
outgoingMessage, err := buildImageWithoutAlbumIDMessage(*ourChat)
|
||||
s.NoError(err)
|
||||
outgoingMessage.Text = "You can edit me now"
|
||||
album = append(album, outgoingMessage)
|
||||
}
|
||||
|
||||
err = s.m.SaveChat(ourChat)
|
||||
s.NoError(err)
|
||||
response, err := s.m.SendChatMessages(context.Background(), album)
|
||||
s.NoError(err)
|
||||
s.Require().Equal(messageCount, len(response.Messages()), "it returns the messages")
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.Messages(), messageCount)
|
||||
|
||||
response, err = WaitOnMessengerResponse(
|
||||
theirMessenger,
|
||||
func(r *MessengerResponse) bool { return len(r.messages) > 0 },
|
||||
"no messages",
|
||||
)
|
||||
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.Chats(), 1)
|
||||
s.Require().Len(response.Messages(), messageCount)
|
||||
|
||||
for _, message := range response.Messages() {
|
||||
image := message.GetImage()
|
||||
s.Require().NotNil(image, "Message.ID=%s", message.ID)
|
||||
s.Require().NotEmpty(image.AlbumId, "Message.ID=%s", message.ID)
|
||||
}
|
||||
|
||||
firstMessageID, err := types.DecodeHex(album[0].ID)
|
||||
s.Require().NoError(err)
|
||||
|
||||
editedText := "edited"
|
||||
editedMessage := &requests.EditMessage{
|
||||
ID: firstMessageID,
|
||||
Text: editedText,
|
||||
}
|
||||
|
||||
sendResponse, err := s.m.EditMessage(context.Background(), editedMessage)
|
||||
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(sendResponse.Messages(), messageCount)
|
||||
|
||||
for _, message := range sendResponse.Messages() {
|
||||
s.Require().NotEmpty(message.EditedAt)
|
||||
s.Require().Equal(message.Text, editedText)
|
||||
}
|
||||
|
||||
response, err = WaitOnMessengerResponse(
|
||||
theirMessenger,
|
||||
func(r *MessengerResponse) bool { return len(r.messages) > 0 },
|
||||
"no messages",
|
||||
)
|
||||
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(response.Chats(), 1)
|
||||
s.Require().Len(response.Messages(), messageCount)
|
||||
|
||||
for _, message := range response.Messages() {
|
||||
s.Require().NotEmpty(message.EditedAt)
|
||||
s.Require().Equal(message.Text, editedText)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue