diff --git a/Session/Conversations/ConversationVC+Interaction.swift b/Session/Conversations/ConversationVC+Interaction.swift index b2fda1a60..49786dea3 100644 --- a/Session/Conversations/ConversationVC+Interaction.swift +++ b/Session/Conversations/ConversationVC+Interaction.swift @@ -1120,16 +1120,6 @@ extension ConversationVC: ) .retainUntilComplete() } else { - OpenGroupAPI - .reactors( - db, - emoji: emoji, - id: openGroupServerMessageId, - in: openGroup.roomToken, - on: openGroup.server - ) - .retainUntilComplete() - OpenGroupAPI .reactionAdd( db, diff --git a/SessionMessagingKit/Jobs/Types/MessageReceiveJob.swift b/SessionMessagingKit/Jobs/Types/MessageReceiveJob.swift index 6822f1fe0..91bc8c819 100644 --- a/SessionMessagingKit/Jobs/Types/MessageReceiveJob.swift +++ b/SessionMessagingKit/Jobs/Types/MessageReceiveJob.swift @@ -106,30 +106,36 @@ extension MessageReceiveJob { case message case variant case serializedProtoData + case reactions } public let message: Message public let variant: Message.Variant public let serializedProtoData: Data + public let reactions: [Reaction] public init( message: Message, variant: Message.Variant, - proto: SNProtoContent + proto: SNProtoContent, + reactions: [Reaction] ) throws { self.message = message self.variant = variant self.serializedProtoData = try proto.serializedData() + self.reactions = reactions } private init( message: Message, variant: Message.Variant, - serializedProtoData: Data + serializedProtoData: Data, + reactions: [Reaction] ) { self.message = message self.variant = variant self.serializedProtoData = serializedProtoData + self.reactions = reactions } // MARK: - Codable @@ -145,7 +151,8 @@ extension MessageReceiveJob { self = MessageInfo( message: try variant.decode(from: container, forKey: .message), variant: variant, - serializedProtoData: try container.decode(Data.self, forKey: .serializedProtoData) + serializedProtoData: try container.decode(Data.self, forKey: .serializedProtoData), + reactions: try container.decode([Reaction].self, forKey: .reactions) ) } @@ -160,6 +167,7 @@ extension MessageReceiveJob { try container.encode(message, forKey: .message) try container.encode(variant, forKey: .variant) try container.encode(serializedProtoData, forKey: .serializedProtoData) + try container.encode(reactions, forKey: .reactions) } } diff --git a/SessionMessagingKit/Messages/Message.swift b/SessionMessagingKit/Messages/Message.swift index 02333c089..6aeaa1788 100644 --- a/SessionMessagingKit/Messages/Message.swift +++ b/SessionMessagingKit/Messages/Message.swift @@ -3,6 +3,7 @@ import Foundation import GRDB import SessionSnodeKit +import SessionUtilitiesKit /// Abstract base class for `VisibleMessage` and `ControlMessage`. public class Message: Codable { @@ -302,22 +303,21 @@ public extension Message { throw MessageReceiverError.invalidMessage } - if let reactions = message.reactions { - try processRawReceivedReactions( - db, - reactions: reactions, - serverExpirationTimestamp: nil, - serverHash: nil, - openGroupId: openGroupId, - openGroupMessageServerId: message.id, - openGroupServerPublicKey: openGroupServerPublicKey, - dependencies: dependencies - ) - } + let reactions = processRawReceivedReactions( + db, + reactions: message.reactions, + serverExpirationTimestamp: nil, + serverHash: nil, + openGroupId: openGroupId, + openGroupMessageServerId: message.id, + openGroupServerPublicKey: openGroupServerPublicKey, + dependencies: dependencies + ) return try processRawReceivedMessage( db, envelope: envelope, + reactions: reactions, serverExpirationTimestamp: nil, serverHash: nil, openGroupId: openGroupId, @@ -363,35 +363,55 @@ public extension Message { private static func processRawReceivedReactions( _ db: Database, - reactions: [String:OpenGroupAPI.Message.Reaction], + reactions: [String:OpenGroupAPI.Message.Reaction]?, serverExpirationTimestamp: TimeInterval?, serverHash: String?, openGroupId: String? = nil, openGroupMessageServerId: Int64? = nil, openGroupServerPublicKey: String? = nil, dependencies: SMKDependencies = SMKDependencies() - ) throws { - guard let openGroupMessageServerId = openGroupMessageServerId else { return } + ) -> [Reaction] { + var results: [Reaction] = [] + guard let openGroupMessageServerId = openGroupMessageServerId, let reactions = reactions else { return results } + let userPublicKey: String = getUserHexEncodedPublicKey(db) for (encodedEmoji, rawReaction) in reactions { if let emoji = encodedEmoji.removingPercentEncoding, rawReaction.count > 0, - let reactors = rawReaction.reactors?.joined(separator: ",") + let reactors = rawReaction.reactors { - try Reaction( - interactionId: openGroupMessageServerId, - serverHash: nil, - timestampMs: Int64(floor((Date().timeIntervalSince1970 * 1000))), - authorId: reactors, - emoji: emoji, - count: rawReaction.count - ).insert(db) + var count = rawReaction.count + for reactor in reactors { + let reaction = Reaction( + interactionId: openGroupMessageServerId, + serverHash: nil, + timestampMs: Int64(floor((Date().timeIntervalSince1970 * 1000))), + authorId: reactor, + emoji: emoji, + count: count + ) + count = 0 // Only insert the first reaction with the total count of this emoji + results.append(reaction) + } + if rawReaction.you && !reactors.contains(userPublicKey) { + let reaction = Reaction( + interactionId: openGroupMessageServerId, + serverHash: nil, + timestampMs: Int64(floor((Date().timeIntervalSince1970 * 1000))), + authorId: userPublicKey, + emoji: emoji, + count: 0 + ) + results.append(reaction) + } } } + return results } private static func processRawReceivedMessage( _ db: Database, envelope: SNProtoEnvelope, + reactions: [Reaction] = [], serverExpirationTimestamp: TimeInterval?, serverHash: String?, openGroupId: String? = nil, @@ -461,7 +481,8 @@ public extension Message { try MessageReceiveJob.Details.MessageInfo( message: message, variant: variant, - proto: proto + proto: proto, + reactions: reactions ) ) }