Merge branch 'reactions'
|
|
@ -3,7 +3,7 @@
|
|||
@implementation Serialization
|
||||
|
||||
- (NSUInteger)currentLayer {
|
||||
return 107;
|
||||
return 108;
|
||||
}
|
||||
|
||||
- (id _Nullable)parseMessage:(NSData * _Nullable)data {
|
||||
|
|
|
|||
|
|
@ -920,7 +920,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||
}
|
||||
}
|
||||
|
||||
func animateOutToReaction(value: String, into targetNode: ASImageNode, hideNode: Bool, completion: @escaping () -> Void) {
|
||||
func animateOutToReaction(value: String, into targetNode: ASDisplayNode, hideNode: Bool, completion: @escaping () -> Void) {
|
||||
guard let reactionContextNode = self.reactionContextNode else {
|
||||
self.animateOut(result: .default, completion: completion)
|
||||
return
|
||||
|
|
@ -1481,7 +1481,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
|
|||
self.dismiss(result: .default, completion: completion)
|
||||
}
|
||||
|
||||
public func dismissWithReaction(value: String, into targetNode: ASImageNode, hideNode: Bool, completion: (() -> Void)?) {
|
||||
public func dismissWithReaction(value: String, into targetNode: ASDisplayNode, hideNode: Bool, completion: (() -> Void)?) {
|
||||
if !self.wasDismissed {
|
||||
self.wasDismissed = true
|
||||
self.controllerNode.animateOutToReaction(value: value, into: targetNode, hideNode: hideNode, completion: { [weak self] in
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public extension CALayer {
|
|||
animation.isAdditive = additive
|
||||
|
||||
if !delay.isZero {
|
||||
animation.beginTime = CACurrentMediaTime() + delay
|
||||
animation.beginTime = CACurrentMediaTime() + delay * UIView.animationDurationFactor()
|
||||
animation.fillMode = .both
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +101,7 @@ public extension CALayer {
|
|||
}
|
||||
|
||||
if !delay.isZero {
|
||||
animation.beginTime = CACurrentMediaTime() + delay
|
||||
animation.beginTime = CACurrentMediaTime() + delay * UIView.animationDurationFactor()
|
||||
animation.fillMode = .both
|
||||
}
|
||||
|
||||
|
|
@ -178,7 +178,7 @@ public extension CALayer {
|
|||
}
|
||||
|
||||
if !delay.isZero {
|
||||
animation.beginTime = CACurrentMediaTime() + delay
|
||||
animation.beginTime = CACurrentMediaTime() + delay * UIView.animationDurationFactor()
|
||||
animation.fillMode = .both
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -377,14 +377,12 @@ public final class ReactionContextNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
|
||||
public func animateOutToReaction(value: String, targetNode: ASImageNode, hideNode: Bool, completion: @escaping () -> Void) {
|
||||
public func animateOutToReaction(value: String, targetNode: ASDisplayNode, hideNode: Bool, completion: @escaping () -> Void) {
|
||||
for itemNode in self.itemNodes {
|
||||
switch itemNode.reaction {
|
||||
case let .reaction(itemValue, _, _):
|
||||
if itemValue == value {
|
||||
if let snapshotView = itemNode.view.snapshotContentTree(keepTransform: true) {
|
||||
let targetSnapshotView = UIImageView()
|
||||
targetSnapshotView.image = targetNode.image
|
||||
if let snapshotView = itemNode.view.snapshotContentTree(keepTransform: true), let targetSnapshotView = targetNode.view.snapshotContentTree() {
|
||||
targetSnapshotView.frame = self.view.convert(targetNode.bounds, from: targetNode.view)
|
||||
itemNode.isHidden = true
|
||||
self.view.addSubview(targetSnapshotView)
|
||||
|
|
|
|||
|
|
@ -255,7 +255,11 @@ final class ReactionSelectionNode: ASDisplayNode {
|
|||
let backgroundHeight: CGFloat = floor(self.minimizedReactionSize * 1.8)
|
||||
|
||||
var backgroundFrame = CGRect(origin: CGPoint(x: -shadowBlur, y: -shadowBlur), size: CGSize(width: contentWidth + shadowBlur * 2.0, height: backgroundHeight + shadowBlur * 2.0))
|
||||
backgroundFrame = backgroundFrame.offsetBy(dx: floor((constrainedSize.width - contentWidth) / 2.0), dy: startingPoint.y - backgroundHeight - 12.0)
|
||||
if constrainedSize.width > 500.0 {
|
||||
backgroundFrame = backgroundFrame.offsetBy(dx: constrainedSize.width - contentWidth - 44.0, dy: startingPoint.y - backgroundHeight - 12.0)
|
||||
} else {
|
||||
backgroundFrame = backgroundFrame.offsetBy(dx: floor((constrainedSize.width - contentWidth) / 2.0), dy: startingPoint.y - backgroundHeight - 12.0)
|
||||
}
|
||||
backgroundFrame.origin.x = max(0.0, backgroundFrame.minX)
|
||||
backgroundFrame.origin.x = min(constrainedSize.width - backgroundFrame.width, backgroundFrame.minX)
|
||||
|
||||
|
|
@ -383,9 +387,9 @@ final class ReactionSelectionNode: ASDisplayNode {
|
|||
|
||||
let backgroundOffset: CGPoint
|
||||
if self.isRightAligned {
|
||||
backgroundOffset = CGPoint(x: (self.backgroundNode.frame.width - shadowBlur) / 2.0 - 42.0, y: (self.backgroundNode.frame.height - shadowBlur) / 2.0)
|
||||
backgroundOffset = CGPoint(x: (self.backgroundNode.frame.width - shadowBlur) / 2.0 - 42.0, y: 10.0)
|
||||
} else {
|
||||
backgroundOffset = CGPoint(x: -(self.backgroundNode.frame.width - shadowBlur) / 2.0 + 42.0, y: (self.backgroundNode.frame.height - shadowBlur) / 2.0)
|
||||
backgroundOffset = CGPoint(x: -(self.backgroundNode.frame.width - shadowBlur) / 2.0 + 42.0, y: 10.0)
|
||||
}
|
||||
let damping: CGFloat = 100.0
|
||||
|
||||
|
|
@ -393,14 +397,15 @@ final class ReactionSelectionNode: ASDisplayNode {
|
|||
let animationOffset: Double = 1.0 - Double(i) / Double(self.reactionNodes.count - 1)
|
||||
var nodeOffset: CGPoint
|
||||
if self.isRightAligned {
|
||||
nodeOffset = CGPoint(x: self.reactionNodes[i].frame.minX - (self.backgroundNode.frame.maxX - shadowBlur) / 2.0 - 42.0, y: self.reactionNodes[i].frame.minY - self.backgroundNode.frame.maxY - shadowBlur)
|
||||
nodeOffset = CGPoint(x: self.reactionNodes[i].frame.minX - (self.backgroundNode.frame.maxX - shadowBlur) / 2.0 - 42.0, y: 10.0)
|
||||
} else {
|
||||
nodeOffset = CGPoint(x: self.reactionNodes[i].frame.minX - (self.backgroundNode.frame.minX + shadowBlur) / 2.0 - 42.0, y: self.reactionNodes[i].frame.minY - self.backgroundNode.frame.maxY - shadowBlur)
|
||||
nodeOffset = CGPoint(x: self.reactionNodes[i].frame.minX - (self.backgroundNode.frame.minX + shadowBlur) / 2.0 - 42.0, y: 10.0)
|
||||
}
|
||||
nodeOffset.x = -nodeOffset.x
|
||||
nodeOffset.x = 0.0
|
||||
nodeOffset.y = 30.0
|
||||
self.reactionNodes[i].layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5 + animationOffset * 0.28, initialVelocity: 0.0, damping: damping)
|
||||
self.reactionNodes[i].layer.animateSpring(from: NSValue(cgPoint: nodeOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true)
|
||||
self.reactionNodes[i].layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.04, delay: animationOffset * 0.1)
|
||||
self.reactionNodes[i].layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, delay: animationOffset * 0.1, initialVelocity: 0.0, damping: damping)
|
||||
//self.reactionNodes[i].layer.animateSpring(from: NSValue(cgPoint: nodeOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, delay: animationOffset * 0.1, initialVelocity: 0.0, damping: damping, additive: true)
|
||||
}
|
||||
|
||||
self.backgroundNode.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, damping: damping)
|
||||
|
|
@ -409,7 +414,7 @@ final class ReactionSelectionNode: ASDisplayNode {
|
|||
self.backgroundShadowNode.layer.animateSpring(from: NSValue(cgPoint: backgroundOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true)
|
||||
}
|
||||
|
||||
func animateOut(into targetNode: ASImageNode?, hideTarget: Bool, completion: @escaping () -> Void) {
|
||||
func animateOut(into targetNode: ASDisplayNode?, hideTarget: Bool, completion: @escaping () -> Void) {
|
||||
self.hapticFeedback.prepareTap()
|
||||
|
||||
var completedContainer = false
|
||||
|
|
@ -424,9 +429,8 @@ final class ReactionSelectionNode: ASDisplayNode {
|
|||
if let targetNode = targetNode {
|
||||
for i in 0 ..< self.reactionNodes.count {
|
||||
if let isMaximized = self.reactionNodes[i].isMaximized, isMaximized {
|
||||
if let snapshotView = self.reactionNodes[i].view.snapshotContentTree() {
|
||||
let targetSnapshotView = UIImageView()
|
||||
targetSnapshotView.image = targetNode.image
|
||||
targetNode.recursivelyEnsureDisplaySynchronously(true)
|
||||
if let snapshotView = self.reactionNodes[i].view.snapshotContentTree(), let targetSnapshotView = targetNode.view.snapshotContentTree() {
|
||||
targetSnapshotView.frame = self.view.convert(targetNode.bounds, from: targetNode.view)
|
||||
self.reactionNodes[i].isHidden = true
|
||||
self.view.addSubview(targetSnapshotView)
|
||||
|
|
@ -485,7 +489,7 @@ final class ReactionSelectionNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
|
||||
self.backgroundNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
//self.backgroundNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
self.backgroundShadowNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
self.backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
self.backgroundShadowNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public final class ReactionSelectionParentNode: ASDisplayNode {
|
|||
return nil
|
||||
}
|
||||
|
||||
func dismissReactions(into targetNode: ASImageNode?, hideTarget: Bool) {
|
||||
func dismissReactions(into targetNode: ASDisplayNode?, hideTarget: Bool) {
|
||||
if let currentNode = self.currentNode {
|
||||
currentNode.animateOut(into: targetNode, hideTarget: hideTarget, completion: { [weak currentNode] in
|
||||
currentNode?.removeFromSupernode()
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ public final class ReactionSwipeGestureRecognizer: UIPanGestureRecognizer {
|
|||
}
|
||||
let elevate = self.shouldElevateAnchorPoint?() ?? false
|
||||
|
||||
let activationTimer = Timer(timeInterval: elevate ? 0.1 : 0.01, target: TimerTarget { [weak self] in
|
||||
let activationTimer = Timer(timeInterval: elevate ? 0.15 : 0.01, target: TimerTarget { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -178,7 +178,7 @@ public final class ReactionSwipeGestureRecognizer: UIPanGestureRecognizer {
|
|||
}
|
||||
}
|
||||
|
||||
public func complete(into targetNode: ASImageNode?, hideTarget: Bool) {
|
||||
public func complete(into targetNode: ASDisplayNode?, hideTarget: Bool) {
|
||||
if self.isAwaitingCompletion {
|
||||
self.currentContainer?.dismissReactions(into: targetNode, hideTarget: hideTarget)
|
||||
self.state = .ended
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[570911930] = { return $0.readInt64() }
|
||||
dict[571523412] = { return $0.readDouble() }
|
||||
dict[-1255641564] = { return parseString($0) }
|
||||
dict[-475111160] = { return Api.MessageReactionsList.parse_messageReactionsList($0) }
|
||||
dict[-1240849242] = { return Api.messages.StickerSet.parse_stickerSet($0) }
|
||||
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
|
||||
dict[-206066487] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
|
||||
|
|
@ -243,6 +244,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[967122427] = { return Api.Update.parse_updateNewScheduledMessage($0) }
|
||||
dict[-1870238482] = { return Api.Update.parse_updateDeleteScheduledMessages($0) }
|
||||
dict[-2112423005] = { return Api.Update.parse_updateTheme($0) }
|
||||
dict[357013699] = { return Api.Update.parse_updateMessageReactions($0) }
|
||||
dict[-2027964103] = { return Api.Update.parse_updateGeoLiveViewed($0) }
|
||||
dict[1448076945] = { return Api.Update.parse_updateLoginToken($0) }
|
||||
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
||||
|
|
@ -286,6 +288,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[1012306921] = { return Api.InputTheme.parse_inputTheme($0) }
|
||||
dict[-175567375] = { return Api.InputTheme.parse_inputThemeSlug($0) }
|
||||
dict[1158290442] = { return Api.messages.FoundGifs.parse_foundGifs($0) }
|
||||
dict[-1199954735] = { return Api.MessageReactions.parse_messageReactions($0) }
|
||||
dict[-1132476723] = { return Api.FileLocation.parse_fileLocationToBeDeprecated($0) }
|
||||
dict[-716006138] = { return Api.Poll.parse_poll($0) }
|
||||
dict[423314455] = { return Api.InputNotifyPeer.parse_inputNotifyUsers($0) }
|
||||
|
|
@ -564,7 +567,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-1820043071] = { return Api.User.parse_user($0) }
|
||||
dict[-2082087340] = { return Api.Message.parse_messageEmpty($0) }
|
||||
dict[-1642487306] = { return Api.Message.parse_messageService($0) }
|
||||
dict[1160515173] = { return Api.Message.parse_message($0) }
|
||||
dict[-1752573244] = { return Api.Message.parse_message($0) }
|
||||
dict[186120336] = { return Api.messages.RecentStickers.parse_recentStickersNotModified($0) }
|
||||
dict[586395571] = { return Api.messages.RecentStickers.parse_recentStickers($0) }
|
||||
dict[-182231723] = { return Api.InputFileLocation.parse_inputEncryptedFileLocation($0) }
|
||||
|
|
@ -619,6 +622,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-1625153079] = { return Api.InputWebFileLocation.parse_inputWebFileGeoPointLocation($0) }
|
||||
dict[-332168592] = { return Api.MessageFwdHeader.parse_messageFwdHeader($0) }
|
||||
dict[398898678] = { return Api.help.Support.parse_support($0) }
|
||||
dict[1873957073] = { return Api.ReactionCount.parse_reactionCount($0) }
|
||||
dict[1474492012] = { return Api.MessagesFilter.parse_inputMessagesFilterEmpty($0) }
|
||||
dict[-1777752804] = { return Api.MessagesFilter.parse_inputMessagesFilterPhotos($0) }
|
||||
dict[-1614803355] = { return Api.MessagesFilter.parse_inputMessagesFilterVideo($0) }
|
||||
|
|
@ -646,6 +650,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-1449145777] = { return Api.upload.CdnFile.parse_cdnFile($0) }
|
||||
dict[1984136919] = { return Api.wallet.LiteResponse.parse_liteResponse($0) }
|
||||
dict[415997816] = { return Api.help.InviteText.parse_inviteText($0) }
|
||||
dict[-764945220] = { return Api.MessageUserReaction.parse_messageUserReaction($0) }
|
||||
dict[-1937807902] = { return Api.BotInlineMessage.parse_botInlineMessageText($0) }
|
||||
dict[982505656] = { return Api.BotInlineMessage.parse_botInlineMessageMediaGeo($0) }
|
||||
dict[1984755728] = { return Api.BotInlineMessage.parse_botInlineMessageMediaAuto($0) }
|
||||
|
|
@ -845,6 +850,8 @@ public struct Api {
|
|||
|
||||
public static func serializeObject(_ object: Any, buffer: Buffer, boxed: Swift.Bool) {
|
||||
switch object {
|
||||
case let _1 as Api.MessageReactionsList:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.StickerSet:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputGeoPoint:
|
||||
|
|
@ -979,6 +986,8 @@ public struct Api {
|
|||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.FoundGifs:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.MessageReactions:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.FileLocation:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.Poll:
|
||||
|
|
@ -1271,6 +1280,8 @@ public struct Api {
|
|||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.help.Support:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.ReactionCount:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.MessagesFilter:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.Dialogs:
|
||||
|
|
@ -1283,6 +1294,8 @@ public struct Api {
|
|||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.help.InviteText:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.MessageUserReaction:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.BotInlineMessage:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.InputPeerNotifySettings:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,66 @@
|
|||
public extension Api {
|
||||
public enum MessageReactionsList: TypeConstructorDescription {
|
||||
case messageReactionsList(flags: Int32, count: Int32, reactions: [Api.MessageUserReaction], users: [Api.User], nextOffset: String?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .messageReactionsList(let flags, let count, let reactions, let users, let nextOffset):
|
||||
if boxed {
|
||||
buffer.appendInt32(-475111160)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(reactions.count))
|
||||
for item in reactions {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .messageReactionsList(let flags, let count, let reactions, let users, let nextOffset):
|
||||
return ("messageReactionsList", [("flags", flags), ("count", count), ("reactions", reactions), ("users", users), ("nextOffset", nextOffset)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_messageReactionsList(_ reader: BufferReader) -> MessageReactionsList? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: [Api.MessageUserReaction]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageUserReaction.self)
|
||||
}
|
||||
var _4: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
var _5: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_5 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.MessageReactionsList.messageReactionsList(flags: _1!, count: _2!, reactions: _3!, users: _4!, nextOffset: _5)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum InputGeoPoint: TypeConstructorDescription {
|
||||
case inputGeoPointEmpty
|
||||
case inputGeoPoint(lat: Double, long: Double)
|
||||
|
|
@ -4082,6 +4144,7 @@ public extension Api {
|
|||
case updateNewScheduledMessage(message: Api.Message)
|
||||
case updateDeleteScheduledMessages(peer: Api.Peer, messages: [Int32])
|
||||
case updateTheme(theme: Api.Theme)
|
||||
case updateMessageReactions(peer: Api.Peer, msgId: Int32, reactions: Api.MessageReactions)
|
||||
case updateGeoLiveViewed(peer: Api.Peer, msgId: Int32)
|
||||
case updateLoginToken
|
||||
|
||||
|
|
@ -4708,6 +4771,14 @@ public extension Api {
|
|||
}
|
||||
theme.serialize(buffer, true)
|
||||
break
|
||||
case .updateMessageReactions(let peer, let msgId, let reactions):
|
||||
if boxed {
|
||||
buffer.appendInt32(357013699)
|
||||
}
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
reactions.serialize(buffer, true)
|
||||
break
|
||||
case .updateGeoLiveViewed(let peer, let msgId):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2027964103)
|
||||
|
|
@ -4874,6 +4945,8 @@ public extension Api {
|
|||
return ("updateDeleteScheduledMessages", [("peer", peer), ("messages", messages)])
|
||||
case .updateTheme(let theme):
|
||||
return ("updateTheme", [("theme", theme)])
|
||||
case .updateMessageReactions(let peer, let msgId, let reactions):
|
||||
return ("updateMessageReactions", [("peer", peer), ("msgId", msgId), ("reactions", reactions)])
|
||||
case .updateGeoLiveViewed(let peer, let msgId):
|
||||
return ("updateGeoLiveViewed", [("peer", peer), ("msgId", msgId)])
|
||||
case .updateLoginToken:
|
||||
|
|
@ -6136,6 +6209,27 @@ public extension Api {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_updateMessageReactions(_ reader: BufferReader) -> Update? {
|
||||
var _1: Api.Peer?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
}
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Api.MessageReactions?
|
||||
if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.MessageReactions
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.Update.updateMessageReactions(peer: _1!, msgId: _2!, reactions: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_updateGeoLiveViewed(_ reader: BufferReader) -> Update? {
|
||||
var _1: Api.Peer?
|
||||
if let signature = reader.readInt32() {
|
||||
|
|
@ -7110,6 +7204,50 @@ public extension Api {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum MessageReactions: TypeConstructorDescription {
|
||||
case messageReactions(flags: Int32, results: [Api.ReactionCount])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .messageReactions(let flags, let results):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1199954735)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(results.count))
|
||||
for item in results {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .messageReactions(let flags, let results):
|
||||
return ("messageReactions", [("flags", flags), ("results", results)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_messageReactions(_ reader: BufferReader) -> MessageReactions? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: [Api.ReactionCount]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.ReactionCount.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.MessageReactions.messageReactions(flags: _1!, results: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum FileLocation: TypeConstructorDescription {
|
||||
case fileLocationToBeDeprecated(volumeId: Int64, localId: Int32)
|
||||
|
|
@ -14222,7 +14360,7 @@ public extension Api {
|
|||
public enum Message: TypeConstructorDescription {
|
||||
case messageEmpty(id: Int32)
|
||||
case messageService(flags: Int32, id: Int32, fromId: Int32?, toId: Api.Peer, replyToMsgId: Int32?, date: Int32, action: Api.MessageAction)
|
||||
case message(flags: Int32, id: Int32, fromId: Int32?, toId: Api.Peer, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int32?, replyToMsgId: Int32?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, restrictionReason: [Api.RestrictionReason]?)
|
||||
case message(flags: Int32, id: Int32, fromId: Int32?, toId: Api.Peer, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int32?, replyToMsgId: Int32?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
|
|
@ -14244,9 +14382,9 @@ public extension Api {
|
|||
serializeInt32(date, buffer: buffer, boxed: false)
|
||||
action.serialize(buffer, true)
|
||||
break
|
||||
case .message(let flags, let id, let fromId, let toId, let fwdFrom, let viaBotId, let replyToMsgId, let date, let message, let media, let replyMarkup, let entities, let views, let editDate, let postAuthor, let groupedId, let restrictionReason):
|
||||
case .message(let flags, let id, let fromId, let toId, let fwdFrom, let viaBotId, let replyToMsgId, let date, let message, let media, let replyMarkup, let entities, let views, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason):
|
||||
if boxed {
|
||||
buffer.appendInt32(1160515173)
|
||||
buffer.appendInt32(-1752573244)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
|
|
@ -14268,6 +14406,7 @@ public extension Api {
|
|||
if Int(flags) & Int(1 << 15) != 0 {serializeInt32(editDate!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 16) != 0 {serializeString(postAuthor!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 17) != 0 {serializeInt64(groupedId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 20) != 0 {reactions!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 22) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(restrictionReason!.count))
|
||||
for item in restrictionReason! {
|
||||
|
|
@ -14283,8 +14422,8 @@ public extension Api {
|
|||
return ("messageEmpty", [("id", id)])
|
||||
case .messageService(let flags, let id, let fromId, let toId, let replyToMsgId, let date, let action):
|
||||
return ("messageService", [("flags", flags), ("id", id), ("fromId", fromId), ("toId", toId), ("replyToMsgId", replyToMsgId), ("date", date), ("action", action)])
|
||||
case .message(let flags, let id, let fromId, let toId, let fwdFrom, let viaBotId, let replyToMsgId, let date, let message, let media, let replyMarkup, let entities, let views, let editDate, let postAuthor, let groupedId, let restrictionReason):
|
||||
return ("message", [("flags", flags), ("id", id), ("fromId", fromId), ("toId", toId), ("fwdFrom", fwdFrom), ("viaBotId", viaBotId), ("replyToMsgId", replyToMsgId), ("date", date), ("message", message), ("media", media), ("replyMarkup", replyMarkup), ("entities", entities), ("views", views), ("editDate", editDate), ("postAuthor", postAuthor), ("groupedId", groupedId), ("restrictionReason", restrictionReason)])
|
||||
case .message(let flags, let id, let fromId, let toId, let fwdFrom, let viaBotId, let replyToMsgId, let date, let message, let media, let replyMarkup, let entities, let views, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason):
|
||||
return ("message", [("flags", flags), ("id", id), ("fromId", fromId), ("toId", toId), ("fwdFrom", fwdFrom), ("viaBotId", viaBotId), ("replyToMsgId", replyToMsgId), ("date", date), ("message", message), ("media", media), ("replyMarkup", replyMarkup), ("entities", entities), ("views", views), ("editDate", editDate), ("postAuthor", postAuthor), ("groupedId", groupedId), ("reactions", reactions), ("restrictionReason", restrictionReason)])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -14375,9 +14514,13 @@ public extension Api {
|
|||
if Int(_1!) & Int(1 << 16) != 0 {_15 = parseString(reader) }
|
||||
var _16: Int64?
|
||||
if Int(_1!) & Int(1 << 17) != 0 {_16 = reader.readInt64() }
|
||||
var _17: [Api.RestrictionReason]?
|
||||
var _17: Api.MessageReactions?
|
||||
if Int(_1!) & Int(1 << 20) != 0 {if let signature = reader.readInt32() {
|
||||
_17 = Api.parse(reader, signature: signature) as? Api.MessageReactions
|
||||
} }
|
||||
var _18: [Api.RestrictionReason]?
|
||||
if Int(_1!) & Int(1 << 22) != 0 {if let _ = reader.readInt32() {
|
||||
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self)
|
||||
_18 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self)
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
|
|
@ -14395,9 +14538,10 @@ public extension Api {
|
|||
let _c14 = (Int(_1!) & Int(1 << 15) == 0) || _14 != nil
|
||||
let _c15 = (Int(_1!) & Int(1 << 16) == 0) || _15 != nil
|
||||
let _c16 = (Int(_1!) & Int(1 << 17) == 0) || _16 != nil
|
||||
let _c17 = (Int(_1!) & Int(1 << 22) == 0) || _17 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
|
||||
return Api.Message.message(flags: _1!, id: _2!, fromId: _3, toId: _4!, fwdFrom: _5, viaBotId: _6, replyToMsgId: _7, date: _8!, message: _9!, media: _10, replyMarkup: _11, entities: _12, views: _13, editDate: _14, postAuthor: _15, groupedId: _16, restrictionReason: _17)
|
||||
let _c17 = (Int(_1!) & Int(1 << 20) == 0) || _17 != nil
|
||||
let _c18 = (Int(_1!) & Int(1 << 22) == 0) || _18 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 {
|
||||
return Api.Message.message(flags: _1!, id: _2!, fromId: _3, toId: _4!, fwdFrom: _5, viaBotId: _6, replyToMsgId: _7, date: _8!, message: _9!, media: _10, replyMarkup: _11, entities: _12, views: _13, editDate: _14, postAuthor: _15, groupedId: _16, reactions: _17, restrictionReason: _18)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
|
@ -15890,6 +16034,48 @@ public extension Api {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum ReactionCount: TypeConstructorDescription {
|
||||
case reactionCount(flags: Int32, reaction: String, count: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .reactionCount(let flags, let reaction, let count):
|
||||
if boxed {
|
||||
buffer.appendInt32(1873957073)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeString(reaction, buffer: buffer, boxed: false)
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .reactionCount(let flags, let reaction, let count):
|
||||
return ("reactionCount", [("flags", flags), ("reaction", reaction), ("count", count)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_reactionCount(_ reader: BufferReader) -> ReactionCount? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.ReactionCount.reactionCount(flags: _1!, reaction: _2!, count: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum MessagesFilter: TypeConstructorDescription {
|
||||
case inputMessagesFilterEmpty
|
||||
|
|
@ -16202,6 +16388,44 @@ public extension Api {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum MessageUserReaction: TypeConstructorDescription {
|
||||
case messageUserReaction(userId: Int32, reaction: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .messageUserReaction(let userId, let reaction):
|
||||
if boxed {
|
||||
buffer.appendInt32(-764945220)
|
||||
}
|
||||
serializeInt32(userId, buffer: buffer, boxed: false)
|
||||
serializeString(reaction, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .messageUserReaction(let userId, let reaction):
|
||||
return ("messageUserReaction", [("userId", userId), ("reaction", reaction)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_messageUserReaction(_ reader: BufferReader) -> MessageUserReaction? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.MessageUserReaction.messageUserReaction(userId: _1!, reaction: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum BotInlineMessage: TypeConstructorDescription {
|
||||
case botInlineMessageText(flags: Int32, message: String, entities: [Api.MessageEntity]?, replyMarkup: Api.ReplyMarkup?)
|
||||
|
|
|
|||
|
|
@ -3161,6 +3161,61 @@ public extension Api {
|
|||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func sendReaction(flags: Int32, peer: Api.InputPeer, msgId: Int32, reaction: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(627641572)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(msgId, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(reaction!, buffer: buffer, boxed: false)}
|
||||
return (FunctionDescription(name: "messages.sendReaction", parameters: [("flags", flags), ("peer", peer), ("msgId", msgId), ("reaction", reaction)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func getMessagesReactions(peer: Api.InputPeer, id: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1950707482)
|
||||
peer.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(id.count))
|
||||
for item in id {
|
||||
serializeInt32(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
return (FunctionDescription(name: "messages.getMessagesReactions", parameters: [("peer", peer), ("id", id)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Updates?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Updates
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func getMessageReactionsList(flags: Int32, peer: Api.InputPeer, id: Int32, reaction: String?, offset: String?, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.MessageReactionsList>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(363935594)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(reaction!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeString(offset!, buffer: buffer, boxed: false)}
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getMessageReactionsList", parameters: [("flags", flags), ("peer", peer), ("id", id), ("reaction", reaction), ("offset", offset), ("limit", limit)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.MessageReactionsList? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.MessageReactionsList?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.MessageReactionsList
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public struct channels {
|
||||
public static func readHistory(channel: Api.InputChannel, maxId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ enum AccountStateMutationOperation {
|
|||
case DeleteMessages([MessageId])
|
||||
case EditMessage(MessageId, StoreMessage)
|
||||
case UpdateMessagePoll(MediaId, Api.Poll?, Api.PollResults)
|
||||
//case UpdateMessageReactions(MessageId, Api.MessageReactions)
|
||||
case UpdateMessageReactions(MessageId, Api.MessageReactions)
|
||||
case UpdateMedia(MediaId, Media?)
|
||||
case ReadInbox(MessageId)
|
||||
case ReadOutbox(MessageId, Int32?)
|
||||
|
|
@ -217,9 +217,9 @@ struct AccountMutableState {
|
|||
self.addOperation(.UpdateMessagePoll(id, poll, results))
|
||||
}
|
||||
|
||||
/*mutating func updateMessageReactions(_ messageId: MessageId, reactions: Api.MessageReactions) {
|
||||
mutating func updateMessageReactions(_ messageId: MessageId, reactions: Api.MessageReactions) {
|
||||
self.addOperation(.UpdateMessageReactions(messageId, reactions))
|
||||
}*/
|
||||
}
|
||||
|
||||
mutating func updateMedia(_ id: MediaId, media: Media?) {
|
||||
self.addOperation(.UpdateMedia(id, media))
|
||||
|
|
@ -404,7 +404,7 @@ struct AccountMutableState {
|
|||
|
||||
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||
switch operation {
|
||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, /*.UpdateMessageReactions,*/ .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme:
|
||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme:
|
||||
break
|
||||
case let .AddMessages(messages, location):
|
||||
for message in messages {
|
||||
|
|
|
|||
|
|
@ -1280,8 +1280,8 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
|||
updatedState.updateLangPack(langCode: langCode, difference: difference)
|
||||
case let .updateMessagePoll(_, pollId, poll, results):
|
||||
updatedState.updateMessagePoll(MediaId(namespace: Namespaces.Media.CloudPoll, id: pollId), poll: poll, results: results)
|
||||
/*case let .updateMessageReactions(peer, msgId, reactions):
|
||||
updatedState.updateMessageReactions(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), reactions: reactions)*/
|
||||
case let .updateMessageReactions(peer, msgId, reactions):
|
||||
updatedState.updateMessageReactions(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), reactions: reactions)
|
||||
case let .updateFolderPeers(folderPeers, _, _):
|
||||
for folderPeer in folderPeers {
|
||||
switch folderPeer {
|
||||
|
|
@ -2025,7 +2025,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
|||
var currentAddScheduledMessages: OptimizeAddMessagesState?
|
||||
for operation in operations {
|
||||
switch operation {
|
||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, /*.UpdateMessageReactions,*/ .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme:
|
||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme:
|
||||
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||
}
|
||||
|
|
@ -2347,7 +2347,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
|||
updatedPoll = updatedPoll.withUpdatedResults(TelegramMediaPollResults(apiResults: results), min: resultsMin)
|
||||
updateMessageMedia(transaction: transaction, id: pollId, media: updatedPoll)
|
||||
}
|
||||
/*case let .UpdateMessageReactions(messageId, reactions):
|
||||
case let .UpdateMessageReactions(messageId, reactions):
|
||||
transaction.updateMessage(messageId, update: { currentMessage in
|
||||
var storeForwardInfo: StoreMessageForwardInfo?
|
||||
if let forwardInfo = currentMessage.forwardInfo {
|
||||
|
|
@ -2366,7 +2366,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
|||
attributes.append(ReactionsMessageAttribute(apiReactions: reactions))
|
||||
}
|
||||
return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, 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))
|
||||
})*/
|
||||
})
|
||||
case let .UpdateMedia(id, media):
|
||||
if let media = media as? TelegramMediaWebpage {
|
||||
updatedWebpages[id] = media
|
||||
|
|
|
|||
|
|
@ -33,9 +33,7 @@ private enum RequestUpdateMessageReactionError {
|
|||
}
|
||||
|
||||
private func requestUpdateMessageReaction(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId) -> Signal<Never, RequestUpdateMessageReactionError> {
|
||||
return .complete()
|
||||
|
||||
/*return postbox.transaction { transaction -> (Peer, String?)? in
|
||||
return postbox.transaction { transaction -> (Peer, String?)? in
|
||||
guard let peer = transaction.getPeer(messageId.peerId) else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -91,7 +89,7 @@ private func requestUpdateMessageReaction(postbox: Postbox, network: Network, st
|
|||
|> castError(RequestUpdateMessageReactionError.self)
|
||||
|> ignoreValues
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
private final class ManagedApplyPendingMessageReactionsActionsHelper {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import TelegramApi
|
|||
|
||||
import SyncCore
|
||||
|
||||
/*extension ReactionsMessageAttribute {
|
||||
extension ReactionsMessageAttribute {
|
||||
func withUpdatedResults(_ reactions: Api.MessageReactions) -> ReactionsMessageAttribute {
|
||||
switch reactions {
|
||||
case let .messageReactions(flags, results):
|
||||
|
|
@ -34,7 +34,7 @@ import SyncCore
|
|||
return ReactionsMessageAttribute(reactions: reactions)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public func mergedMessageReactions(attributes: [MessageAttribute]) -> ReactionsMessageAttribute? {
|
||||
var current: ReactionsMessageAttribute?
|
||||
|
|
@ -86,7 +86,7 @@ public func mergedMessageReactions(attributes: [MessageAttribute]) -> ReactionsM
|
|||
}
|
||||
}
|
||||
|
||||
/*extension ReactionsMessageAttribute {
|
||||
extension ReactionsMessageAttribute {
|
||||
convenience init(apiReactions: Api.MessageReactions) {
|
||||
switch apiReactions {
|
||||
case let .messageReactions(_, results):
|
||||
|
|
@ -99,4 +99,3 @@ public func mergedMessageReactions(attributes: [MessageAttribute]) -> ReactionsM
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
|||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 107
|
||||
return 108
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
|
|||
|
||||
func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
switch message {
|
||||
case let .message(flags, _, fromId, toId, fwdHeader, viaBotId, _, _, _, media, _, entities, _, _, _, _, _):
|
||||
case let .message(flags, _, fromId, toId, fwdHeader, viaBotId, _, _, _, media, _, entities, _, _, _, _, _, _):
|
||||
let peerId: PeerId
|
||||
switch toId {
|
||||
case let .peerUser(userId):
|
||||
|
|
@ -240,7 +240,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
|||
|
||||
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> [MessageId]? {
|
||||
switch message {
|
||||
case let .message(flags, _, fromId, toId, _, _, replyToMsgId, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(flags, _, fromId, toId, _, _, replyToMsgId, _, _, _, _, _, _, _, _, _, _, _):
|
||||
if let replyToMsgId = replyToMsgId {
|
||||
let peerId: PeerId
|
||||
switch toId {
|
||||
|
|
@ -382,7 +382,7 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes
|
|||
extension StoreMessage {
|
||||
convenience init?(apiMessage: Api.Message, namespace: MessageId.Namespace = Namespaces.Message.Cloud) {
|
||||
switch apiMessage {
|
||||
case let .message(flags, id, fromId, toId, fwdFrom, viaBotId, replyToMsgId, date, message, media, replyMarkup, entities, views, editDate, postAuthor, groupingId, restrictionReason):
|
||||
case let .message(flags, id, fromId, toId, fwdFrom, viaBotId, replyToMsgId, date, message, media, replyMarkup, entities, views, editDate, postAuthor, groupingId, reactions, restrictionReason):
|
||||
let peerId: PeerId
|
||||
var authorId: PeerId?
|
||||
switch toId {
|
||||
|
|
@ -537,9 +537,9 @@ extension StoreMessage {
|
|||
attributes.append(ContentRequiresValidationMessageAttribute())
|
||||
}
|
||||
|
||||
/*if let reactions = reactions {
|
||||
if let reactions = reactions {
|
||||
attributes.append(ReactionsMessageAttribute(apiReactions: reactions))
|
||||
}*/
|
||||
}
|
||||
|
||||
if let restrictionReason = restrictionReason {
|
||||
attributes.append(RestrictedContentMessageAttribute(rules: restrictionReason.map(RestrictionRule.init(apiReason:))))
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class UpdateMessageService: NSObject, MTMessageService {
|
|||
self.putNext(groups)
|
||||
}
|
||||
case let .updateShortChatMessage(flags, id, fromId, chatId, message, pts, ptsCount, date, fwdFrom, viaBotId, replyToMsgId, entities):
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: fromId, toId: Api.Peer.peerChat(chatId: chatId), fwdFrom: fwdFrom, viaBotId: viaBotId, replyToMsgId: replyToMsgId, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, editDate: nil, postAuthor: nil, groupedId: nil/*, reactions: nil*/, restrictionReason: nil)
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: fromId, toId: Api.Peer.peerChat(chatId: chatId), fwdFrom: fwdFrom, viaBotId: viaBotId, replyToMsgId: replyToMsgId, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil)
|
||||
let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount)
|
||||
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
|
||||
if groups.count != 0 {
|
||||
|
|
@ -75,7 +75,7 @@ class UpdateMessageService: NSObject, MTMessageService {
|
|||
generatedToId = Api.Peer.peerUser(userId: self.peerId.id)
|
||||
}
|
||||
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: generatedFromId, toId: generatedToId, fwdFrom: fwdFrom, viaBotId: viaBotId, replyToMsgId: replyToMsgId, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, editDate: nil, postAuthor: nil, groupedId: nil/*, reactions: nil*/, restrictionReason: nil)
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: generatedFromId, toId: generatedToId, fwdFrom: fwdFrom, viaBotId: viaBotId, replyToMsgId: replyToMsgId, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil)
|
||||
let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount)
|
||||
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
|
||||
if groups.count != 0 {
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ public final class ChatControllerInteraction {
|
|||
let sendScheduledMessagesNow: ([MessageId]) -> Void
|
||||
let editScheduledMessagesTime: ([MessageId]) -> Void
|
||||
let performTextSelectionAction: (UInt32, String, TextSelectionAction) -> Void
|
||||
let updateMessageReaction: (MessageId, String) -> Void
|
||||
let updateMessageReaction: (MessageId, String?) -> Void
|
||||
let openMessageReactions: (MessageId) -> Void
|
||||
let displaySwipeToReplyHint: () -> Void
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ public final class ChatControllerInteraction {
|
|||
var searchTextHighightState: (String, [MessageIndex])?
|
||||
var seenOneTimeAnimatedMedia = Set<MessageId>()
|
||||
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, TapLongTapOrDoubleTapGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> Bool, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOption: @escaping (MessageId, Data) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, String, TextSelectionAction) -> Void, updateMessageReaction: @escaping (MessageId, String?) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
|
||||
self.openMessage = openMessage
|
||||
self.openPeer = openPeer
|
||||
self.openPeerMention = openPeerMention
|
||||
|
|
|
|||
|
|
@ -1051,7 +1051,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||
return self.contentImageNode?.playMediaWithSound()
|
||||
}
|
||||
|
||||
func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
if !self.statusNode.isHidden {
|
||||
return self.statusNode.reactionNode(value: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ class ChatMessageBubbleContentNode: ASDisplayNode {
|
|||
func updateIsExtractedToContextPreview(_ value: Bool) {
|
||||
}
|
||||
|
||||
func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -522,8 +522,14 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
|||
if let item = strongSelf.item, let reaction = reaction {
|
||||
switch reaction {
|
||||
case let .reaction(value, _, _):
|
||||
strongSelf.awaitingAppliedReaction = (value, {})
|
||||
item.controllerInteraction.updateMessageReaction(item.message.id, value)
|
||||
var resolvedValue: String?
|
||||
if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), reactionsAttribute.reactions.contains(where: { $0.value == value }) {
|
||||
resolvedValue = nil
|
||||
} else {
|
||||
resolvedValue = value
|
||||
}
|
||||
strongSelf.awaitingAppliedReaction = (resolvedValue, {})
|
||||
item.controllerInteraction.updateMessageReaction(item.message.id, resolvedValue)
|
||||
case .reply:
|
||||
strongSelf.reactionRecognizer?.complete(into: nil, hideTarget: false)
|
||||
var bounds = strongSelf.bounds
|
||||
|
|
@ -1994,13 +2000,15 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
|||
}
|
||||
|
||||
strongSelf.awaitingAppliedReaction = nil
|
||||
var targetNode: ASImageNode?
|
||||
var targetNode: ASDisplayNode?
|
||||
var hideTarget = false
|
||||
for contentNode in strongSelf.contentNodes {
|
||||
if let (reactionNode, count) = contentNode.reactionTargetNode(value: awaitingAppliedReaction) {
|
||||
targetNode = reactionNode
|
||||
hideTarget = count == 1
|
||||
break
|
||||
if let awaitingAppliedReaction = awaitingAppliedReaction {
|
||||
for contentNode in strongSelf.contentNodes {
|
||||
if let (reactionNode, count) = contentNode.reactionTargetNode(value: awaitingAppliedReaction) {
|
||||
targetNode = reactionNode
|
||||
hideTarget = count == 1
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
strongSelf.reactionRecognizer?.complete(into: targetNode, hideTarget: hideTarget)
|
||||
|
|
@ -2852,7 +2860,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
|
|||
self.contextSourceNode.contentNode.addSubnode(accessoryItemNode)
|
||||
}
|
||||
|
||||
override func targetReactionNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func targetReactionNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
for contentNode in self.contentNodes {
|
||||
if let (reactionNode, count) = contentNode.reactionTargetNode(value: value) {
|
||||
return (reactionNode, count)
|
||||
|
|
|
|||
|
|
@ -346,7 +346,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
if !self.dateAndStatusNode.isHidden {
|
||||
return self.dateAndStatusNode.reactionNode(value: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import Display
|
|||
import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
import AccountContext
|
||||
import AppBundle
|
||||
|
||||
private let reactionCountFont = Font.semibold(11.0)
|
||||
|
||||
|
|
@ -42,26 +43,90 @@ enum ChatMessageDateAndStatusType: Equatable {
|
|||
case FreeOutgoing(ChatMessageDateAndStatusOutgoingType)
|
||||
}
|
||||
|
||||
private let reactionSize: CGFloat = 19.0
|
||||
private let reactionSize: CGFloat = 20.0
|
||||
private let reactionFont = Font.regular(12.0)
|
||||
|
||||
private final class StatusReactionNode: ASImageNode {
|
||||
private final class StatusReactionNodeParameters: NSObject {
|
||||
let value: String
|
||||
let previousValue: String?
|
||||
|
||||
init(value: String, previousValue: String?) {
|
||||
self.value = value
|
||||
self.previousValue = previousValue
|
||||
}
|
||||
}
|
||||
|
||||
private func drawReaction(context: CGContext, value: String, in rect: CGRect) {
|
||||
var fileId: Int?
|
||||
switch value {
|
||||
case "😔":
|
||||
fileId = 8
|
||||
case "😳":
|
||||
fileId = 19
|
||||
case "😂":
|
||||
fileId = 17
|
||||
case "👍":
|
||||
fileId = 6
|
||||
case "❤":
|
||||
fileId = 13
|
||||
default:
|
||||
break
|
||||
}
|
||||
if let fileId = fileId, let path = getAppBundle().path(forResource: "simplereaction_\(fileId)@2x", ofType: "png"), let image = UIImage(contentsOfFile: path) {
|
||||
context.saveGState()
|
||||
context.translateBy(x: rect.midX, y: rect.midY)
|
||||
context.scaleBy(x: 1.0, y: -1.0)
|
||||
context.translateBy(x: -rect.midX, y: -rect.midY)
|
||||
context.draw(image.cgImage!, in: rect)
|
||||
context.restoreGState()
|
||||
} else {
|
||||
let string = NSAttributedString(string: value, font: reactionFont, textColor: .black)
|
||||
string.draw(at: CGPoint(x: rect.minX + 1.0, y: rect.minY + 3.0))
|
||||
}
|
||||
}
|
||||
|
||||
private final class StatusReactionNode: ASDisplayNode {
|
||||
let value: String
|
||||
var count: Int
|
||||
var previousValue: String? {
|
||||
didSet {
|
||||
self.setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
init(value: String, count: Int) {
|
||||
init(value: String, count: Int, previousValue: String?) {
|
||||
self.value = value
|
||||
self.count = count
|
||||
self.previousValue = previousValue
|
||||
|
||||
super.init()
|
||||
|
||||
self.image = generateImage(CGSize(width: reactionSize, height: reactionSize), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
UIGraphicsPushContext(context)
|
||||
let string = NSAttributedString(string: value, font: reactionFont, textColor: .black)
|
||||
string.draw(at: CGPoint(x: 1.0, y: 3.0))
|
||||
UIGraphicsPopContext()
|
||||
})
|
||||
self.isOpaque = false
|
||||
self.backgroundColor = nil
|
||||
}
|
||||
|
||||
override func drawParameters(forAsyncLayer layer: _ASDisplayLayer) -> NSObjectProtocol? {
|
||||
return StatusReactionNodeParameters(value: self.value, previousValue: self.previousValue)
|
||||
}
|
||||
|
||||
@objc override public class func draw(_ bounds: CGRect, withParameters parameters: Any?, isCancelled: () -> Bool, isRasterizing: Bool) {
|
||||
let context = UIGraphicsGetCurrentContext()!
|
||||
|
||||
if !isRasterizing {
|
||||
context.setBlendMode(.copy)
|
||||
context.setFillColor(UIColor.clear.cgColor)
|
||||
context.fill(bounds)
|
||||
}
|
||||
|
||||
guard let parameters = parameters as? StatusReactionNodeParameters else {
|
||||
return
|
||||
}
|
||||
drawReaction(context: context, value: parameters.value, in: bounds)
|
||||
if let previousValue = parameters.previousValue {
|
||||
let previousRect = bounds.offsetBy(dx: -14.0, dy: 0)
|
||||
context.setBlendMode(.destinationOut)
|
||||
drawReaction(context: context, value: previousValue, in: previousRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -346,9 +411,11 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
|||
|
||||
var reactionCountLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||
|
||||
let reactionSpacing: CGFloat = -4.0
|
||||
let reactionTrailingSpacing: CGFloat = 4.0
|
||||
var reactionInset: CGFloat = 0.0
|
||||
if !reactions.isEmpty {
|
||||
reactionInset = 5.0 + CGFloat(reactions.count) * reactionSize
|
||||
reactionInset = 5.0 + CGFloat(reactions.count) * reactionSize + CGFloat(reactions.count - 1) * reactionSpacing + reactionTrailingSpacing
|
||||
|
||||
var count = 0
|
||||
for reaction in reactions {
|
||||
|
|
@ -499,8 +566,9 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
|||
if strongSelf.reactionNodes.count > i, strongSelf.reactionNodes[i].value == reactions[i].value {
|
||||
node = strongSelf.reactionNodes[i]
|
||||
node.count = Int(reactions[i].count)
|
||||
node.previousValue = i == 0 ? nil : reactions[i - 1].value
|
||||
} else {
|
||||
node = StatusReactionNode(value: reactions[i].value, count: Int(reactions[i].count))
|
||||
node = StatusReactionNode(value: reactions[i].value, count: Int(reactions[i].count), previousValue: i == 0 ? nil : reactions[i - 1].value)
|
||||
if strongSelf.reactionNodes.count > i {
|
||||
let previousNode = strongSelf.reactionNodes[i]
|
||||
if animated {
|
||||
|
|
@ -522,11 +590,15 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
node.frame = CGRect(origin: CGPoint(x: reactionOffset, y: backgroundInsets.top + offset - 3.0), size: CGSize(width: reactionSize, height: reactionSize))
|
||||
reactionOffset += reactionSize
|
||||
reactionOffset += reactionSize + reactionSpacing
|
||||
}
|
||||
if !reactions.isEmpty {
|
||||
reactionOffset += reactionTrailingSpacing
|
||||
}
|
||||
for _ in reactions.count ..< strongSelf.reactionNodes.count {
|
||||
let node = strongSelf.reactionNodes.removeLast()
|
||||
if animated {
|
||||
node.layer.animateScale(from: 1.0, to: 0.1, duration: 0.2, removeOnCompletion: false)
|
||||
node.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak node] _ in
|
||||
node?.removeFromSupernode()
|
||||
})
|
||||
|
|
@ -558,7 +630,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
|
||||
if !strongSelf.reactionNodes.isEmpty {
|
||||
if false, !strongSelf.reactionNodes.isEmpty {
|
||||
if strongSelf.reactionButtonNode == nil {
|
||||
let reactionButtonNode = HighlightTrackingButtonNode()
|
||||
strongSelf.reactionButtonNode = reactionButtonNode
|
||||
|
|
@ -610,7 +682,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
|
||||
func reactionNode(value: String) -> (ASImageNode, Int)? {
|
||||
func reactionNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
for node in self.reactionNodes {
|
||||
if node.value == value {
|
||||
return (node, node.count)
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
self.interactiveFileNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
return self.interactiveFileNode.reactionTargetNode(value: value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
return self.contentNode.transitionNode(media: media)
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
return self.contentNode.reactionTargetNode(value: value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -947,7 +947,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
|||
self.playerUpdateTimer = nil
|
||||
}
|
||||
|
||||
func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
if !self.dateAndStatusNode.isHidden {
|
||||
return self.dateAndStatusNode.reactionNode(value: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
return self.contentNode.transitionNode(media: media)
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
return self.contentNode.reactionTargetNode(value: value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -634,7 +634,7 @@ public class ChatMessageItemView: ListViewItemNode {
|
|||
var item: ChatMessageItem?
|
||||
var accessibilityData: ChatMessageAccessibilityData?
|
||||
|
||||
var awaitingAppliedReaction: (String, () -> Void)?
|
||||
var awaitingAppliedReaction: (String?, () -> Void)?
|
||||
|
||||
public required convenience init() {
|
||||
self.init(layerBacked: false)
|
||||
|
|
@ -814,7 +814,7 @@ public class ChatMessageItemView: ListViewItemNode {
|
|||
}
|
||||
}
|
||||
|
||||
func targetReactionNode(value: String) -> (ASImageNode, Int)? {
|
||||
func targetReactionNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -469,7 +469,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
if !self.dateAndStatusNode.isHidden {
|
||||
return self.dateAndStatusNode.reactionNode(value: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
return false
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
if !self.dateAndStatusNode.isHidden {
|
||||
return self.dateAndStatusNode.reactionNode(value: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -955,7 +955,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
if !self.statusNode.isHidden {
|
||||
return self.statusNode.reactionNode(value: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,7 +245,7 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
self.statusNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
if !self.statusNode.isHidden {
|
||||
return self.statusNode.reactionNode(value: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -579,7 +579,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
}
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
if !self.statusNode.isHidden {
|
||||
return self.statusNode.reactionNode(value: value)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -511,7 +511,7 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
|||
self.contentNode.updateTouchesAtPoint(point.flatMap { $0.offsetBy(dx: -contentNodeFrame.minX, dy: -contentNodeFrame.minY) })
|
||||
}
|
||||
|
||||
override func reactionTargetNode(value: String) -> (ASImageNode, Int)? {
|
||||
override func reactionTargetNode(value: String) -> (ASDisplayNode, Int)? {
|
||||
return self.contentNode.reactionTargetNode(value: value)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 2 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 5.4 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 3 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 4 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.3 KiB |