diff --git a/build-system/bazel-rules/apple_support b/build-system/bazel-rules/apple_support index a448644dce..c1f83903e8 160000 --- a/build-system/bazel-rules/apple_support +++ b/build-system/bazel-rules/apple_support @@ -1 +1 @@ -Subproject commit a448644dce247e59268864fd66b6578195412b59 +Subproject commit c1f83903e864d753477e51d66d3ada6c2c6d096f diff --git a/build-system/bazel-rules/rules_apple b/build-system/bazel-rules/rules_apple index 4ebd7cc45e..fcbfcfad2d 160000 --- a/build-system/bazel-rules/rules_apple +++ b/build-system/bazel-rules/rules_apple @@ -1 +1 @@ -Subproject commit 4ebd7cc45edfe6c525c1553a0f5294895653c9df +Subproject commit fcbfcfad2d633b6c8be85954975db88bee3fa26c diff --git a/build-system/bazel-rules/rules_swift b/build-system/bazel-rules/rules_swift index e850484071..03c89782e9 160000 --- a/build-system/bazel-rules/rules_swift +++ b/build-system/bazel-rules/rules_swift @@ -1 +1 @@ -Subproject commit e850484071d2b8dc41685a62d3567c312173f3c3 +Subproject commit 03c89782e9a15d467c7e036ee36f9adb6bdda910 diff --git a/build-system/tulsi b/build-system/tulsi index 4eb4edc06e..ec7dd9ddf4 160000 --- a/build-system/tulsi +++ b/build-system/tulsi @@ -1 +1 @@ -Subproject commit 4eb4edc06eef85d0a4593f36e8fe34e33f718018 +Subproject commit ec7dd9ddf4b73dedb02df827b7ab3b2cbb1f2ac0 diff --git a/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift b/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift index 16ece5bc68..8c66f0c2ca 100644 --- a/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift +++ b/submodules/MediaPlayer/Sources/SoftwareVideoSource.swift @@ -1,5 +1,9 @@ import Foundation +#if !os(macOS) import UIKit +#else +import AppKit +#endif import CoreMedia import SwiftSignalKit import FFMpegBinding diff --git a/submodules/MediaPlayer/Sources/UniversalSoftwareVideoSource.swift b/submodules/MediaPlayer/Sources/UniversalSoftwareVideoSource.swift index 8bd13e88f8..4fed8b6d85 100644 --- a/submodules/MediaPlayer/Sources/UniversalSoftwareVideoSource.swift +++ b/submodules/MediaPlayer/Sources/UniversalSoftwareVideoSource.swift @@ -1,5 +1,9 @@ import Foundation +#if !os(macOS) import UIKit +#else +import AppKit +#endif import SwiftSignalKit import Postbox import TelegramCore diff --git a/submodules/OpenSSLEncryptionProvider/Package.swift b/submodules/OpenSSLEncryptionProvider/Package.swift new file mode 100644 index 0000000000..c70a67dc33 --- /dev/null +++ b/submodules/OpenSSLEncryptionProvider/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version:5.5 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + + +let package = Package( + name: "OpenSSLEncryption", + platforms: [ + .macOS(.v10_11) + ], + products: [ + .library( + name: "OpenSSLEncryption", + targets: ["OpenSSLEncryption"]), + ], + targets: [ + .target( + name: "OpenSSLEncryption", + dependencies: [], + path: ".", + exclude: ["BUILD"], + publicHeadersPath: "PublicHeaders", + cSettings: [ + .headerSearchPath("PublicHeaders"), + .unsafeFlags([ + "-I../../../../core-xprojects/openssl/build/openssl/include", + "-I../EncryptionProvider/PublicHeaders" + ]) + ]), + ] +) diff --git a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift index c27c3e73e0..cf0845ff5d 100644 --- a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift +++ b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift @@ -610,7 +610,7 @@ struct AccountFinalState { struct AccountReplayedFinalState { let state: AccountFinalState let addedIncomingMessageIds: [MessageId] - let addedReactionEvents: [(reactionAuthor: Peer, message: Message, timestamp: Int32)] + let addedReactionEvents: [(reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)] let wasScheduledMessageIds: [MessageId] let addedSecretMessageIds: [MessageId] let deletedMessageIds: [DeletedMessageId] @@ -628,7 +628,7 @@ struct AccountReplayedFinalState { struct AccountFinalStateEvents { let addedIncomingMessageIds: [MessageId] - let addedReactionEvents: [(reactionAuthor: Peer, message: Message, timestamp: Int32)] + let addedReactionEvents: [(reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)] let wasScheduledMessageIds:[MessageId] let deletedMessageIds: [DeletedMessageId] let updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] @@ -651,7 +651,7 @@ struct AccountFinalStateEvents { return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty } - init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:]) { + init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:]) { self.addedIncomingMessageIds = addedIncomingMessageIds self.addedReactionEvents = addedReactionEvents self.wasScheduledMessageIds = wasScheduledMessageIds diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 4efc5b7060..a42ec55260 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -4,6 +4,43 @@ import SwiftSignalKit import TelegramApi import MtProtoKit +private func reactionGeneratedEvent(_ previousReactions: ReactionsMessageAttribute?, _ updatedReactions: ReactionsMessageAttribute?, message: Message, transaction: Transaction) -> (reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)? { + + if let updatedReactions = updatedReactions, !message.flags.contains(.Incoming), message.id.peerId.namespace == Namespaces.Peer.CloudUser { + let prev = previousReactions?.reactions ?? [] + + let updated = updatedReactions.reactions.filter { value in + return !prev.contains(where: { + $0.value == value.value && $0.count == value.count + }) + } + let myUpdated = updatedReactions.reactions.filter { value in + return value.isSelected + }.first + let myPrevious = prev.filter { value in + return value.isSelected + }.first + + let previousCount = prev.reduce(0, { + $0 + $1.count + }) + let updatedCount = updatedReactions.reactions.reduce(0, { + $0 + $1.count + }) + + let newReaction = updated.filter { + !$0.isSelected + }.first?.value + + if !updated.isEmpty && myUpdated == myPrevious, updatedCount >= previousCount, let value = newReaction { + if let reactionAuthor = transaction.getPeer(message.id.peerId) { + return (reactionAuthor: reactionAuthor, reaction: value, message: message, timestamp: Int32(Date().timeIntervalSince1970)) + } + } + } + return nil +} + private func peerIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> Set { var peerIds = Set() @@ -2430,7 +2467,7 @@ func replayFinalState( } var wasScheduledMessageIds:[MessageId] = [] var addedIncomingMessageIds: [MessageId] = [] - var addedReactionEvents: [(reactionAuthor: Peer, message: Message, timestamp: Int32)] = [] + var addedReactionEvents: [(reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)] = [] if !wasOperationScheduledMessageIds.isEmpty { let existingIds = transaction.filterStoredMessageIds(Set(wasOperationScheduledMessageIds)) @@ -2670,6 +2707,7 @@ func replayFinalState( invalidateGroupStats.insert(Namespaces.PeerGroup.archive) } case let .EditMessage(id, message): + var generatedEvent: (reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)? transaction.updateMessage(id, update: { previousMessage in var updatedFlags = message.flags var updatedLocalTags = message.localTags @@ -2681,8 +2719,21 @@ func replayFinalState( } else { updatedFlags.remove(.Incoming) } + + let peers: [PeerId:Peer] = previousMessage.peers.reduce([:], { current, value in + var current = current + current[value.0] = value.1 + return current + }) + + if let message = locallyRenderedMessage(message: message, peers: peers) { + generatedEvent = reactionGeneratedEvent(previousMessage.reactionsAttribute, message.reactionsAttribute, message: message, transaction: transaction) + } return .update(message.withUpdatedLocalTags(updatedLocalTags).withUpdatedFlags(updatedFlags)) }) + if let generatedEvent = generatedEvent { + addedReactionEvents.append(generatedEvent) + } case let .UpdateMessagePoll(pollId, apiPoll, results): if let poll = transaction.getMedia(pollId) as? TelegramMediaPoll { var updatedPoll = poll @@ -3230,7 +3281,7 @@ func replayFinalState( }) } case let .UpdateMessageReactions(messageId, reactions, eventTimestamp): - var generatedEvent: (reactionAuthor: Peer, message: Message, timestamp: Int32)? + var generatedEvent: (reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)? transaction.updateMessage(messageId, update: { currentMessage in var updatedReactions = ReactionsMessageAttribute(apiReactions: reactions) @@ -3254,45 +3305,9 @@ func replayFinalState( if !added { attributes.append(updatedReactions) } - - if let eventTimestamp = eventTimestamp, !currentMessage.flags.contains(.Incoming), let chatPeer = currentMessage.peers[currentMessage.id.peerId] { - let _ = chatPeer - - var previousCount = 0 - if let previousReactions = previousReactions { - for reaction in previousReactions.reactions { - previousCount += Int(reaction.count) - } - } - - var updatedCount = 0 - for reaction in updatedReactions.reactions { - updatedCount += Int(reaction.count) - } - - if updatedCount > previousCount { - if let topPeer = updatedReactions.recentPeers.last { - var wasPresentBefore = false - if let previousReactions = previousReactions { - for recentPeer in previousReactions.recentPeers { - if recentPeer.peerId == topPeer.peerId { - wasPresentBefore = true - break - } - } - } - if !wasPresentBefore, let reactionAuthor = transaction.getPeer(topPeer.peerId), transaction.isPeerContact(peerId: topPeer.peerId) { - generatedEvent = (reactionAuthor: reactionAuthor, message: currentMessage.withUpdatedAttributes(attributes), timestamp: eventTimestamp) - } - } - } - } - + return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) }) - if let generatedEvent = generatedEvent { - addedReactionEvents.append(generatedEvent) - } } } diff --git a/submodules/TelegramCore/Sources/State/AccountStateManager.swift b/submodules/TelegramCore/Sources/State/AccountStateManager.swift index a832e6a134..46d078be08 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManager.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManager.swift @@ -105,8 +105,8 @@ public final class AccountStateManager { return self.notificationMessagesPipe.signal() } - private let reactionNotificationsPipe = ValuePipe<[(reactionAuthor: Peer, message: Message)]>() - public var reactionNotifications: Signal<[(reactionAuthor: Peer, message: Message)], NoError> { + private let reactionNotificationsPipe = ValuePipe<[(reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)]>() + public var reactionNotifications: Signal<[(reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)], NoError> { return self.reactionNotificationsPipe.signal() } @@ -746,16 +746,15 @@ public final class AccountStateManager { let timestamp = Int32(Date().timeIntervalSince1970) let minReactionTimestamp = timestamp - 20 - let reactionEvents = events.addedReactionEvents.compactMap { event -> (reactionAuthor: Peer, message: Message)? in + let reactionEvents = events.addedReactionEvents.compactMap { event -> (reactionAuthor: Peer, reaction: String, message: Message, timestamp: Int32)? in if event.timestamp >= minReactionTimestamp { - return (event.reactionAuthor, event.message) + return (event.reactionAuthor, event.reaction, event.message, event.timestamp) } else { return nil } } - if !reactionEvents.isEmpty { - self.reactionNotificationsPipe.putNext(reactionEvents) - } + self.reactionNotificationsPipe.putNext(reactionEvents) + if !events.displayAlerts.isEmpty { self.displayAlertsPipe.putNext(events.displayAlerts) diff --git a/submodules/TelegramCore/Sources/State/MessageReactions.swift b/submodules/TelegramCore/Sources/State/MessageReactions.swift index d964dc54e0..de6ac7cb1b 100644 --- a/submodules/TelegramCore/Sources/State/MessageReactions.swift +++ b/submodules/TelegramCore/Sources/State/MessageReactions.swift @@ -19,6 +19,7 @@ public func updateMessageReactionsInteractively(account: Account, messageId: Mes break loop } } + attributes.append(PendingReactionsMessageAttribute(accountPeerId: account.peerId, value: reaction)) return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) }) @@ -245,7 +246,9 @@ public extension EngineMessageReactionListContext.State { } for recentPeer in reactionsAttribute.recentPeers { if let peer = message.peers[recentPeer.peerId] { - items.append(EngineMessageReactionListContext.Item(peer: EnginePeer(peer), reaction: recentPeer.value)) + if reaction == nil || recentPeer.value == reaction { + items.append(EngineMessageReactionListContext.Item(peer: EnginePeer(peer), reaction: recentPeer.value)) + } } } } @@ -337,6 +340,8 @@ public final class EngineMessageReactionListContext { if initialState.canLoadMore { self.loadMore() + } else { + self.statePromise.set(.single(self.state)) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ProxySettings.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ProxySettings.swift index dc386d20d8..4413812ce7 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ProxySettings.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ProxySettings.swift @@ -66,6 +66,7 @@ public struct ProxyServerSettings: Codable, Equatable, Hashable { public func hash(into hasher: inout Hasher) { hasher.combine(self.host) + hasher.combine(self.port) hasher.combine(self.connection) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift index 4315937127..7cb0b530ec 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift @@ -7,11 +7,6 @@ public struct MessageReaction: Equatable, PostboxCoding { public init(value: String, count: Int32, isSelected: Bool) { var value = value - - if value == "❤️" { - value = "❤" - } - self.value = value self.count = count self.isSelected = isSelected diff --git a/submodules/TelegramCore/Sources/Utils/MessageUtils.swift b/submodules/TelegramCore/Sources/Utils/MessageUtils.swift index ff7393ebaf..6a13ab787c 100644 --- a/submodules/TelegramCore/Sources/Utils/MessageUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/MessageUtils.swift @@ -322,6 +322,19 @@ public extension Message { } return nil } + var hasReactions: Bool { + for attribute in self.attributes { + if let attribute = attribute as? ReactionsMessageAttribute { + return !attribute.reactions.isEmpty + } + } + for attribute in self.attributes { + if let attribute = attribute as? PendingReactionsMessageAttribute { + return attribute.value != nil + } + } + return false + } var textEntitiesAttribute: TextEntitiesMessageAttribute? { for attribute in self.attributes {