Merge pull request #676 from RyanRory/emoji-reacts-tweaks

Emoji reacts open group poll & update conflict handling
pull/678/head
RyanZhao 3 years ago committed by GitHub
commit d5a1c310f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -138,6 +138,8 @@
7B7CB192271508AD0079FF93 /* CallRingTonePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB191271508AD0079FF93 /* CallRingTonePlayer.swift */; }; 7B7CB192271508AD0079FF93 /* CallRingTonePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB191271508AD0079FF93 /* CallRingTonePlayer.swift */; };
7B81682328A4C1210069F315 /* UpdateTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682228A4C1210069F315 /* UpdateTypes.swift */; }; 7B81682328A4C1210069F315 /* UpdateTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682228A4C1210069F315 /* UpdateTypes.swift */; };
7B81682828B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682728B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift */; }; 7B81682828B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682728B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift */; };
7B81682A28B6F1420069F315 /* ReactionResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682928B6F1420069F315 /* ReactionResponse.swift */; };
7B81682C28B72F480069F315 /* PendingChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B81682B28B72F480069F315 /* PendingChange.swift */; };
7B8D5FC428332600008324D9 /* VisibleMessage+Reaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8D5FC328332600008324D9 /* VisibleMessage+Reaction.swift */; }; 7B8D5FC428332600008324D9 /* VisibleMessage+Reaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8D5FC328332600008324D9 /* VisibleMessage+Reaction.swift */; };
7B93D06A27CF173D00811CB6 /* MessageRequestsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B93D06927CF173D00811CB6 /* MessageRequestsViewController.swift */; }; 7B93D06A27CF173D00811CB6 /* MessageRequestsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B93D06927CF173D00811CB6 /* MessageRequestsViewController.swift */; };
7B93D07027CF194000811CB6 /* ConfigurationMessage+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B93D06E27CF194000811CB6 /* ConfigurationMessage+Convenience.swift */; }; 7B93D07027CF194000811CB6 /* ConfigurationMessage+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B93D06E27CF194000811CB6 /* ConfigurationMessage+Convenience.swift */; };
@ -1178,6 +1180,8 @@
7B7CB191271508AD0079FF93 /* CallRingTonePlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallRingTonePlayer.swift; sourceTree = "<group>"; }; 7B7CB191271508AD0079FF93 /* CallRingTonePlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallRingTonePlayer.swift; sourceTree = "<group>"; };
7B81682228A4C1210069F315 /* UpdateTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateTypes.swift; sourceTree = "<group>"; }; 7B81682228A4C1210069F315 /* UpdateTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateTypes.swift; sourceTree = "<group>"; };
7B81682728B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _007_HomeQueryOptimisationIndexes.swift; sourceTree = "<group>"; }; 7B81682728B310D50069F315 /* _007_HomeQueryOptimisationIndexes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _007_HomeQueryOptimisationIndexes.swift; sourceTree = "<group>"; };
7B81682928B6F1420069F315 /* ReactionResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReactionResponse.swift; sourceTree = "<group>"; };
7B81682B28B72F480069F315 /* PendingChange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PendingChange.swift; sourceTree = "<group>"; };
7B8D5FC328332600008324D9 /* VisibleMessage+Reaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisibleMessage+Reaction.swift"; sourceTree = "<group>"; }; 7B8D5FC328332600008324D9 /* VisibleMessage+Reaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VisibleMessage+Reaction.swift"; sourceTree = "<group>"; };
7B93D06927CF173D00811CB6 /* MessageRequestsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageRequestsViewController.swift; sourceTree = "<group>"; }; 7B93D06927CF173D00811CB6 /* MessageRequestsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageRequestsViewController.swift; sourceTree = "<group>"; };
7B93D06E27CF194000811CB6 /* ConfigurationMessage+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ConfigurationMessage+Convenience.swift"; sourceTree = "<group>"; }; 7B93D06E27CF194000811CB6 /* ConfigurationMessage+Convenience.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ConfigurationMessage+Convenience.swift"; sourceTree = "<group>"; };
@ -3853,6 +3857,8 @@
FDC438A327BB107F00C60D73 /* UserBanRequest.swift */, FDC438A327BB107F00C60D73 /* UserBanRequest.swift */,
FDC438A527BB113A00C60D73 /* UserUnbanRequest.swift */, FDC438A527BB113A00C60D73 /* UserUnbanRequest.swift */,
FDC438A927BB12BB00C60D73 /* UserModeratorRequest.swift */, FDC438A927BB12BB00C60D73 /* UserModeratorRequest.swift */,
7B81682928B6F1420069F315 /* ReactionResponse.swift */,
7B81682B28B72F480069F315 /* PendingChange.swift */,
); );
path = Models; path = Models;
sourceTree = "<group>"; sourceTree = "<group>";
@ -5190,6 +5196,7 @@
C3471ECB2555356A00297E91 /* MessageSender+Encryption.swift in Sources */, C3471ECB2555356A00297E91 /* MessageSender+Encryption.swift in Sources */,
FDF40CDE2897A1BC006A0CC4 /* _004_RemoveLegacyYDB.swift in Sources */, FDF40CDE2897A1BC006A0CC4 /* _004_RemoveLegacyYDB.swift in Sources */,
FDF0B74928060D13004C14C5 /* QuotedReplyModel.swift in Sources */, FDF0B74928060D13004C14C5 /* QuotedReplyModel.swift in Sources */,
7B81682C28B72F480069F315 /* PendingChange.swift in Sources */,
FD77289A284AF1BD0018502F /* Sodium+Utilities.swift in Sources */, FD77289A284AF1BD0018502F /* Sodium+Utilities.swift in Sources */,
FD5C7309285007920029977D /* BlindedIdLookup.swift in Sources */, FD5C7309285007920029977D /* BlindedIdLookup.swift in Sources */,
7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */, 7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */,
@ -5203,6 +5210,7 @@
FD6A7A6B2818C17C00035AC1 /* UpdateProfilePictureJob.swift in Sources */, FD6A7A6B2818C17C00035AC1 /* UpdateProfilePictureJob.swift in Sources */,
FD716E6A2850327900C96BF4 /* EndCallMode.swift in Sources */, FD716E6A2850327900C96BF4 /* EndCallMode.swift in Sources */,
FDF0B75C2807F41D004C14C5 /* MessageSender+Convenience.swift in Sources */, FDF0B75C2807F41D004C14C5 /* MessageSender+Convenience.swift in Sources */,
7B81682A28B6F1420069F315 /* ReactionResponse.swift in Sources */,
FD09799727FFA84A00936362 /* RecipientState.swift in Sources */, FD09799727FFA84A00936362 /* RecipientState.swift in Sources */,
FDA8EB00280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift in Sources */, FDA8EB00280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift in Sources */,
FD09798927FD1C5A00936362 /* OpenGroup.swift in Sources */, FD09798927FD1C5A00936362 /* OpenGroup.swift in Sources */,

@ -1137,6 +1137,14 @@ extension ConversationVC:
else { return } else { return }
if remove { if remove {
let pendingChange = OpenGroupManager
.addPendingReaction(
emoji: emoji,
id: openGroupServerMessageId,
in: openGroup.roomToken,
on: openGroup.server,
type: .remove
)
OpenGroupAPI OpenGroupAPI
.reactionDelete( .reactionDelete(
db, db,
@ -1145,8 +1153,23 @@ extension ConversationVC:
in: openGroup.roomToken, in: openGroup.roomToken,
on: openGroup.server on: openGroup.server
) )
.map { _, response in
OpenGroupManager
.updatePendingChange(
pendingChange,
seqNo: response.seqNo
)
}
.retainUntilComplete() .retainUntilComplete()
} else { } else {
let pendingChange = OpenGroupManager
.addPendingReaction(
emoji: emoji,
id: openGroupServerMessageId,
in: openGroup.roomToken,
on: openGroup.server,
type: .react
)
OpenGroupAPI OpenGroupAPI
.reactionAdd( .reactionAdd(
db, db,
@ -1155,6 +1178,13 @@ extension ConversationVC:
in: openGroup.roomToken, in: openGroup.roomToken,
on: openGroup.server on: openGroup.server
) )
.map { _, response in
OpenGroupManager
.updatePendingChange(
pendingChange,
seqNo: response.seqNo
)
}
.retainUntilComplete() .retainUntilComplete()
} }

@ -353,6 +353,7 @@ public extension Message {
_ db: Database, _ db: Database,
openGroupId: String, openGroupId: String,
message: OpenGroupAPI.Message, message: OpenGroupAPI.Message,
associatedPendingChanges: [OpenGroupAPI.PendingChange],
dependencies: SMKDependencies = SMKDependencies() dependencies: SMKDependencies = SMKDependencies()
) -> [Reaction] { ) -> [Reaction] {
var results: [Reaction] = [] var results: [Reaction] = []
@ -364,13 +365,46 @@ public extension Message {
threadVariant: .openGroup threadVariant: .openGroup
) )
for (encodedEmoji, rawReaction) in reactions { for (encodedEmoji, rawReaction) in reactions {
if let emoji = encodedEmoji.removingPercentEncoding, if let decodedEmoji = encodedEmoji.removingPercentEncoding,
rawReaction.count > 0, rawReaction.count > 0,
let reactors = rawReaction.reactors let reactors = rawReaction.reactors
{ {
// Decide whether we need to add an extra reaction from current user
let pendingChangeSelfReaction: Bool? = {
// Find the newest 'PendingChange' entry with a matching emoji, if one exists, and
// set the "self reaction" value based on it's action
let maybePendingChange: OpenGroupAPI.PendingChange? = associatedPendingChanges
.sorted(by: { lhs, rhs -> Bool in (lhs.seqNo ?? Int64.max) > (rhs.seqNo ?? Int64.max) })
.first { pendingChange in
if case .reaction(_, let emoji, _) = pendingChange.metadata {
return emoji == decodedEmoji
}
return false
}
// If there is no pending change for this reaction then return nil
guard
let pendingChange: OpenGroupAPI.PendingChange = maybePendingChange,
case .reaction(_, _, let action) = pendingChange.metadata
else { return nil }
// Otherwise add/remove accordingly
return (action == .react)
}()
let shouldAddSelfReaction: Bool = (
pendingChangeSelfReaction ??
(rawReaction.you || reactors.contains(userPublicKey))
)
let count: Int64 = rawReaction.you ? rawReaction.count - 1 : rawReaction.count
let timestampMs: Int64 = Int64(floor((Date().timeIntervalSince1970 * 1000))) let timestampMs: Int64 = Int64(floor((Date().timeIntervalSince1970 * 1000)))
let maxLength: Int = shouldAddSelfReaction ? 4 : 5
let desiredReactorIds: [String] = reactors let desiredReactorIds: [String] = reactors
.filter { $0 != blindedUserPublicKey } .filter { $0 != blindedUserPublicKey && $0 != userPublicKey } // Remove current user for now, will add back if needed
.prefix(maxLength)
.map{ $0 }
results = results results = results
.appending( // Add the first reaction (with the count) .appending( // Add the first reaction (with the count)
@ -381,8 +415,8 @@ public extension Message {
serverHash: nil, serverHash: nil,
timestampMs: timestampMs, timestampMs: timestampMs,
authorId: reactor, authorId: reactor,
emoji: emoji, emoji: decodedEmoji,
count: rawReaction.count, count: count,
sortId: rawReaction.index sortId: rawReaction.index
) )
} }
@ -398,22 +432,22 @@ public extension Message {
serverHash: nil, serverHash: nil,
timestampMs: timestampMs, timestampMs: timestampMs,
authorId: reactor, authorId: reactor,
emoji: emoji, emoji: decodedEmoji,
count: 0, // Only want this on the first reaction count: 0, // Only want this on the first reaction
sortId: rawReaction.index sortId: rawReaction.index
) )
} }
) )
.appending( // Add the current user reaction (if applicable and not already included) .appending( // Add the current user reaction (if applicable and not already included)
!rawReaction.you || reactors.contains(userPublicKey) ? !shouldAddSelfReaction ?
nil : nil :
Reaction( Reaction(
interactionId: message.id, interactionId: message.id,
serverHash: nil, serverHash: nil,
timestampMs: timestampMs, timestampMs: timestampMs,
authorId: userPublicKey, authorId: userPublicKey,
emoji: emoji, emoji: decodedEmoji,
count: (desiredReactorIds.isEmpty ? rawReaction.count : 0), count: 1,
sortId: rawReaction.index sortId: rawReaction.index
) )
) )

@ -0,0 +1,41 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
extension OpenGroupAPI {
public struct PendingChange: Equatable {
enum ChangeType {
case reaction
}
enum Metadata {
case reaction(messageId: Int64, emoji: String, action: VisibleMessage.VMReaction.Kind)
}
let server: String
let room: String
let changeType: ChangeType
var seqNo: Int64?
let metadata: Metadata
public static func == (lhs: OpenGroupAPI.PendingChange, rhs: OpenGroupAPI.PendingChange) -> Bool {
guard lhs.server == rhs.server &&
lhs.room == rhs.room &&
lhs.changeType == rhs.changeType &&
lhs.seqNo == rhs.seqNo
else {
return false
}
switch lhs.changeType {
case .reaction:
if case .reaction(let lhsMessageId, let lhsEmoji, let lhsAction) = lhs.metadata,
case .reaction(let rhsMessageId, let rhsEmoji, let rhsAction) = rhs.metadata {
return lhsMessageId == rhsMessageId && lhsEmoji == rhsEmoji && lhsAction == rhsAction
} else {
return false
}
}
}
}
}

@ -0,0 +1,44 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
extension OpenGroupAPI {
public struct ReactionAddResponse: Codable, Equatable {
enum CodingKeys: String, CodingKey {
case added
case seqNo = "seqno"
}
/// This field indicates whether the reaction was added (true) or already present (false).
public let added: Bool
/// The seqNo after the reaction is added.
public let seqNo: Int64
}
public struct ReactionRemoveResponse: Codable, Equatable {
enum CodingKeys: String, CodingKey {
case removed
case seqNo = "seqno"
}
/// This field indicates whether the reaction was removed (true) or was not present to begin with (false).
public let removed: Bool
/// The seqNo after the reaction is removed.
public let seqNo: Int64
}
public struct ReactionRemoveAllResponse: Codable, Equatable {
enum CodingKeys: String, CodingKey {
case removed
case seqNo = "seqno"
}
/// This field shows the total number of reactions that were deleted.
public let removed: Int64
/// The seqNo after the reactions is all removed.
public let seqNo: Int64
}
}

@ -99,7 +99,7 @@ public enum OpenGroupAPI {
), ),
queryParameters: [ queryParameters: [
.updateTypes: UpdateTypes.reaction.rawValue, .updateTypes: UpdateTypes.reaction.rawValue,
.reactors: "20" .reactors: "5"
] ]
), ),
responseType: [Failable<Message>].self responseType: [Failable<Message>].self
@ -701,7 +701,7 @@ public enum OpenGroupAPI {
in roomToken: String, in roomToken: String,
on server: String, on server: String,
using dependencies: SMKDependencies = SMKDependencies() using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<OnionRequestResponseInfoType> { ) -> Promise<(OnionRequestResponseInfoType, ReactionAddResponse)> {
/// URL(String:) won't convert raw emojis, so need to do a little encoding here. /// URL(String:) won't convert raw emojis, so need to do a little encoding here.
/// The raw emoji will come back when calling url.path /// The raw emoji will come back when calling url.path
guard let encodedEmoji: String = emoji.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { guard let encodedEmoji: String = emoji.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else {
@ -718,7 +718,7 @@ public enum OpenGroupAPI {
), ),
using: dependencies using: dependencies
) )
.map { responseInfo, _ in responseInfo } .decoded(as: ReactionAddResponse.self, on: OpenGroupAPI.workQueue, using: dependencies)
} }
public static func reactionDelete( public static func reactionDelete(
@ -728,7 +728,7 @@ public enum OpenGroupAPI {
in roomToken: String, in roomToken: String,
on server: String, on server: String,
using dependencies: SMKDependencies = SMKDependencies() using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<OnionRequestResponseInfoType> { ) -> Promise<(OnionRequestResponseInfoType, ReactionRemoveResponse)> {
/// URL(String:) won't convert raw emojis, so need to do a little encoding here. /// URL(String:) won't convert raw emojis, so need to do a little encoding here.
/// The raw emoji will come back when calling url.path /// The raw emoji will come back when calling url.path
guard let encodedEmoji: String = emoji.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { guard let encodedEmoji: String = emoji.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else {
@ -745,7 +745,7 @@ public enum OpenGroupAPI {
), ),
using: dependencies using: dependencies
) )
.map { responseInfo, _ in responseInfo } .decoded(as: ReactionRemoveResponse.self, on: OpenGroupAPI.workQueue, using: dependencies)
} }
public static func reactionDeleteAll( public static func reactionDeleteAll(
@ -755,7 +755,7 @@ public enum OpenGroupAPI {
in roomToken: String, in roomToken: String,
on server: String, on server: String,
using dependencies: SMKDependencies = SMKDependencies() using dependencies: SMKDependencies = SMKDependencies()
) -> Promise<OnionRequestResponseInfoType> { ) -> Promise<(OnionRequestResponseInfoType, ReactionRemoveAllResponse)> {
/// URL(String:) won't convert raw emojis, so need to do a little encoding here. /// URL(String:) won't convert raw emojis, so need to do a little encoding here.
/// The raw emoji will come back when calling url.path /// The raw emoji will come back when calling url.path
guard let encodedEmoji: String = emoji.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else { guard let encodedEmoji: String = emoji.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) else {
@ -772,7 +772,7 @@ public enum OpenGroupAPI {
), ),
using: dependencies using: dependencies
) )
.map { responseInfo, _ in responseInfo } .decoded(as: ReactionRemoveAllResponse.self, on: OpenGroupAPI.workQueue, using: dependencies)
} }
// MARK: - Pinning // MARK: - Pinning

@ -20,6 +20,8 @@ public protocol OGMCacheType {
var timeSinceLastPoll: [String: TimeInterval] { get set } var timeSinceLastPoll: [String: TimeInterval] { get set }
func getTimeSinceLastOpen(using dependencies: Dependencies) -> TimeInterval func getTimeSinceLastOpen(using dependencies: Dependencies) -> TimeInterval
var pendingChanges: [OpenGroupAPI.PendingChange] { get set }
} }
// MARK: - OpenGroupManager // MARK: - OpenGroupManager
@ -53,6 +55,8 @@ public final class OpenGroupManager: NSObject {
_timeSinceLastOpen = dependencies.date.timeIntervalSince(lastOpen) _timeSinceLastOpen = dependencies.date.timeIntervalSince(lastOpen)
return dependencies.date.timeIntervalSince(lastOpen) return dependencies.date.timeIntervalSince(lastOpen)
} }
public var pendingChanges: [OpenGroupAPI.PendingChange] = []
} }
// MARK: - Variables // MARK: - Variables
@ -529,11 +533,17 @@ public final class OpenGroupManager: NSObject {
.filter { $0.deleted == true } .filter { $0.deleted == true }
.map { $0.id } .map { $0.id }
// Update the 'openGroupSequenceNumber' value (Note: SOGS V4 uses the 'seqNo' instead of the 'serverId')
if let seqNo: Int64 = seqNo { if let seqNo: Int64 = seqNo {
// Update the 'openGroupSequenceNumber' value (Note: SOGS V4 uses the 'seqNo' instead of the 'serverId')
_ = try? OpenGroup _ = try? OpenGroup
.filter(id: openGroup.id) .filter(id: openGroup.id)
.updateAll(db, OpenGroup.Columns.sequenceNumber.set(to: seqNo)) .updateAll(db, OpenGroup.Columns.sequenceNumber.set(to: seqNo))
// Update pendingChange cache
dependencies.mutableCache.mutate {
$0.pendingChanges = $0.pendingChanges
.filter { $0.seqNo == nil || $0.seqNo! > seqNo }
}
} }
// Process the messages // Process the messages
@ -589,11 +599,23 @@ public final class OpenGroupManager: NSObject {
db, db,
openGroupId: openGroup.id, openGroupId: openGroup.id,
message: message, message: message,
associatedPendingChanges: dependencies.cache.pendingChanges
.filter {
guard $0.server == server && $0.room == roomToken && $0.changeType == .reaction else {
return false
}
if case .reaction(let messageId, _, _) = $0.metadata {
return messageId == message.id
}
return false
},
dependencies: dependencies dependencies: dependencies
) )
try MessageReceiver.handleOpenGroupReactions( try MessageReceiver.handleOpenGroupReactions(
db, db,
threadId: openGroup.threadId,
openGroupMessageServerId: message.id, openGroupMessageServerId: message.id,
openGroupReactions: reactions openGroupReactions: reactions
) )
@ -737,6 +759,44 @@ public final class OpenGroupManager: NSObject {
// MARK: - Convenience // MARK: - Convenience
public static func addPendingReaction(
emoji: String,
id: Int64,
in roomToken: String,
on server: String,
type: VisibleMessage.VMReaction.Kind,
using dependencies: OGMDependencies = OGMDependencies()
) -> OpenGroupAPI.PendingChange {
let pendingChange = OpenGroupAPI.PendingChange(
server: server,
room: roomToken,
changeType: .reaction,
metadata: .reaction(
messageId: id,
emoji: emoji,
action: type
)
)
dependencies.mutableCache.mutate {
$0.pendingChanges.append(pendingChange)
}
return pendingChange
}
public static func updatePendingChange(
_ pendingChange: OpenGroupAPI.PendingChange,
seqNo: Int64,
using dependencies: OGMDependencies = OGMDependencies()
) {
dependencies.mutableCache.mutate {
if let index = $0.pendingChanges.firstIndex(of: pendingChange) {
$0.pendingChanges[index].seqNo = seqNo
}
}
}
/// This method specifies if the given capability is supported on a specified Open Group /// This method specifies if the given capability is supported on a specified Open Group
public static func isOpenGroupSupport( public static func isOpenGroupSupport(
_ capability: Capability.Variant, _ capability: Capability.Variant,

@ -249,11 +249,13 @@ public enum MessageReceiver {
public static func handleOpenGroupReactions( public static func handleOpenGroupReactions(
_ db: Database, _ db: Database,
threadId: String,
openGroupMessageServerId: Int64, openGroupMessageServerId: Int64,
openGroupReactions: [Reaction] openGroupReactions: [Reaction]
) throws { ) throws {
guard let interactionId: Int64 = try? Interaction guard let interactionId: Int64 = try? Interaction
.select(.id) .select(.id)
.filter(Interaction.Columns.threadId == threadId)
.filter(Interaction.Columns.openGroupServerMessageId == openGroupMessageServerId) .filter(Interaction.Columns.openGroupServerMessageId == openGroupMessageServerId)
.asRequest(of: Int64.self) .asRequest(of: Int64.self)
.fetchOne(db) .fetchOne(db)

Loading…
Cancel
Save