[WIP] Stars reactions

This commit is contained in:
Isaac 2024-07-30 23:44:19 +08:00
parent 83be782893
commit 05372b578c
85 changed files with 2271 additions and 1115 deletions

View File

@ -2171,6 +2171,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
messageText = item.presentationData.strings.ChatList_UserReacted(value).string
case .custom:
break
case .stars:
break
}
break loop
}

View File

@ -175,6 +175,10 @@ public final class ReactionIconView: PortalSourceView {
iconSize = CGSize(width: floor(size.width * 1.25), height: floor(size.height * 1.25))
animationLayer.masksToBounds = true
animationLayer.cornerRadius = floor(size.width * 0.2)
case .stars:
iconSize = CGSize(width: floor(size.width * 2.0), height: floor(size.height * 2.0))
animationLayer.masksToBounds = false
animationLayer.cornerRadius = 0.0
}
transition.updateFrame(layer: animationLayer, frame: CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize))
@ -207,6 +211,8 @@ public final class ReactionIconView: PortalSourceView {
iconSize = CGSize(width: floor(size.width * 2.0), height: floor(size.height * 2.0))
case .custom:
iconSize = CGSize(width: floor(size.width * 1.25), height: floor(size.height * 1.25))
case .stars:
iconSize = CGSize(width: floor(size.width * 2.0), height: floor(size.height * 2.0))
}
let animationLayer = InlineStickerItemLayer(
@ -234,6 +240,9 @@ public final class ReactionIconView: PortalSourceView {
case .custom:
animationLayer.masksToBounds = true
animationLayer.cornerRadius = floor(size.width * 0.3)
case .stars:
animationLayer.masksToBounds = false
animationLayer.cornerRadius = 0.0
}
animationLayer.frame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0)), size: iconSize)
@ -766,7 +775,7 @@ public final class ReactionButtonAsyncNode: ContextControllerSourceView {
let backgroundColors: ReactionButtonAsyncNode.ContainerButtonNode.Colors
if case .custom(MessageReaction.starsReactionId) = spec.component.reaction.value {
if case .stars = spec.component.reaction.value {
backgroundColors = ReactionButtonAsyncNode.ContainerButtonNode.Colors(
background: spec.component.chosenOrder != nil ? spec.component.colors.selectedStarsBackground : spec.component.colors.deselectedStarsBackground,
foreground: spec.component.chosenOrder != nil ? spec.component.colors.selectedStarsForeground : spec.component.colors.deselectedStarsForeground,
@ -821,6 +830,8 @@ public final class ReactionButtonAsyncNode: ContextControllerSourceView {
private let iconImageDisposable = MetaDisposable()
private var ignoreButtonTap: Bool = false
public var activateAfterCompletion: Bool = false {
didSet {
if self.activateAfterCompletion {
@ -881,6 +892,20 @@ public final class ReactionButtonAsyncNode: ContextControllerSourceView {
}
}
}
self.contextGesture?.cancelGesturesOnActivation = { [weak self] in
guard let self else {
return
}
self.buttonNode.isUserInteractionEnabled = false
self.buttonNode.cancelTracking(with: nil)
DispatchQueue.main.async { [weak self] in
guard let self else {
return
}
self.buttonNode.isUserInteractionEnabled = true
}
}
}
required init?(coder aDecoder: NSCoder) {
@ -902,6 +927,9 @@ public final class ReactionButtonAsyncNode: ContextControllerSourceView {
guard let layout = self.layout else {
return
}
if self.ignoreButtonTap {
return
}
layout.spec.component.action(self, layout.spec.component.reaction.value, self.containerView)
}
@ -911,7 +939,7 @@ public final class ReactionButtonAsyncNode: ContextControllerSourceView {
self.containerView.contentRect = CGRect(origin: CGPoint(), size: layout.size)
animation.animator.updateFrame(layer: self.buttonNode.layer, frame: CGRect(origin: CGPoint(), size: layout.size), completion: nil)
if case .custom(MessageReaction.starsReactionId) = layout.spec.component.reaction.value {
if case .stars = layout.spec.component.reaction.value {
let starsEffectLayer: StarsButtonEffectLayer
if let current = self.starsEffectLayer {
starsEffectLayer = current
@ -1319,7 +1347,7 @@ public final class ReactionButtonsAsyncLayoutContainer {
})
if let index = reactions.firstIndex(where: {
if case .custom(MessageReaction.starsReactionId) = $0.reaction.value {
if case .stars = $0.reaction.value {
return true
} else {
return false

View File

@ -164,6 +164,16 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
strongSelf.file = file
strongSelf.updateReactionLayer()
}).strict()
case .stars:
if let availableReactions = availableReactions {
for availableReaction in availableReactions.reactions {
if availableReaction.value == reaction {
self.file = availableReaction.centerAnimation
self.updateReactionLayer()
break
}
}
}
}
} else {
let iconNode = ASImageNode()
@ -574,6 +584,17 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
strongSelf.updateReactionLayer()
strongSelf.updateReactionAccentColor(theme: presentationData.theme)
}).strict()
case .stars:
if let availableReactions = self.availableReactions {
for availableReaction in availableReactions.reactions {
if availableReaction.value == reaction {
self.file = availableReaction.centerAnimation
self.updateReactionLayer()
self.updateReactionAccentColor(theme: presentationData.theme)
break
}
}
}
}
} else {
self.file = nil
@ -598,6 +619,8 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
reactionStringValue = value
case .custom:
reactionStringValue = ""
case .stars:
reactionStringValue = "Star"
}
} else {
reactionStringValue = ""

View File

@ -1329,9 +1329,9 @@ final class ContextControllerNode: ViewControllerTracingNode, ASScrollViewDelega
}
}
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, completion: @escaping () -> Void) {
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, onHit: (() -> Void)?, completion: @escaping () -> Void) {
if let sourceContainer = self.sourceContainer {
sourceContainer.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: reducedCurve, completion: completion)
sourceContainer.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: reducedCurve, onHit: onHit, completion: completion)
}
}
@ -2604,7 +2604,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
} else if let args = self.dismissToReactionOnInputClose {
self.dismissToReactionOnInputClose = nil
DispatchQueue.main.async {
self.dismissWithReactionImpl(value: args.value, targetView: args.targetView, hideNode: args.hideNode, animateTargetContainer: args.animateTargetContainer, addStandaloneReactionAnimation: args.addStandaloneReactionAnimation, reducedCurve: true, completion: args.completion)
self.dismissWithReactionImpl(value: args.value, targetView: args.targetView, hideNode: args.hideNode, animateTargetContainer: args.animateTargetContainer, addStandaloneReactionAnimation: args.addStandaloneReactionAnimation, reducedCurve: true, onHit: nil, completion: args.completion)
}
}
}
@ -2706,11 +2706,11 @@ public final class ContextController: ViewController, StandalonePresentableContr
self.dismissed?()
}
public func dismissWithReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, completion: (() -> Void)?) {
self.dismissWithReactionImpl(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: false, completion: completion)
public func dismissWithReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, onHit: (() -> Void)?, completion: (() -> Void)?) {
self.dismissWithReactionImpl(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: false, onHit: onHit, completion: completion)
}
private func dismissWithReactionImpl(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, completion: (() -> Void)?) {
private func dismissWithReactionImpl(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, onHit: (() -> Void)?, completion: (() -> Void)?) {
if viewTreeContainsFirstResponder(view: self.view) {
self.dismissToReactionOnInputClose = (value, targetView, hideNode, animateTargetContainer, addStandaloneReactionAnimation, completion)
self.view.endEditing(true)
@ -2719,7 +2719,7 @@ public final class ContextController: ViewController, StandalonePresentableContr
if !self.wasDismissed {
self.wasDismissed = true
self.controllerNode.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: reducedCurve, completion: { [weak self] in
self.controllerNode.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: reducedCurve, onHit: onHit, completion: { [weak self] in
self?.presentingViewController?.dismiss(animated: false, completion: nil)
completion?()
})

View File

@ -1668,7 +1668,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
}
}
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, completion: @escaping () -> Void) {
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, onHit: (() -> Void)?, completion: @escaping () -> Void) {
guard let reactionContextNode = self.reactionContextNode else {
self.requestAnimateOut(.default, completion)
return
@ -1697,7 +1697,7 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
intermediateCompletion()
})
reactionContextNode.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, completion: { [weak self] in
reactionContextNode.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, onHit: onHit, completion: { [weak self] in
guard let strongSelf = self else {
return
}

View File

@ -28,7 +28,7 @@ protocol ContextControllerPresentationNode: ASDisplayNode {
stateTransition: ContextControllerPresentationNodeStateTransition?
)
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, completion: @escaping () -> Void)
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, onHit: (() -> Void)?, completion: @escaping () -> Void)
func cancelReactionAnimation()
func highlightGestureMoved(location: CGPoint, hover: Bool)

View File

@ -269,8 +269,8 @@ final class ContextSourceContainer: ASDisplayNode {
self.presentationNode.cancelReactionAnimation()
}
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, completion: @escaping () -> Void) {
self.presentationNode.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: reducedCurve, completion: completion)
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, onHit: (() -> Void)?, completion: @escaping () -> Void) {
self.presentationNode.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: reducedCurve, onHit: onHit, completion: completion)
}
func setItems(items: Signal<ContextController.Items, NoError>, animated: Bool) {
@ -543,9 +543,9 @@ final class ContextSourceContainer: ASDisplayNode {
}
}
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, completion: @escaping () -> Void) {
func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, reducedCurve: Bool, onHit: (() -> Void)?, completion: @escaping () -> Void) {
if let activeSource = self.activeSource {
activeSource.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: reducedCurve, completion: completion)
activeSource.animateOutToReaction(value: value, targetView: targetView, hideNode: hideNode, animateTargetContainer: animateTargetContainer, addStandaloneReactionAnimation: addStandaloneReactionAnimation, reducedCurve: reducedCurve, onHit: onHit, completion: completion)
} else {
completion()
}

View File

@ -264,6 +264,24 @@ public class DrawingReactionEntityView: DrawingStickerEntityView {
}
})
}
case .stars:
let _ = (self.context.engine.stickers.availableReactions()
|> take(1)
|> deliverOnMainQueue).start(next: { availableReactions in
guard let availableReactions else {
return
}
var animation: TelegramMediaFile?
for reaction in availableReactions.reactions {
if reaction.value == updateReaction.reaction {
animation = reaction.selectAnimation
break
}
}
if let animation {
continueWithAnimationFile(animation)
}
})
}
}

View File

@ -538,7 +538,7 @@ public func peerAllowedReactionListController(
}
if initialAllowedReactions != .known(updatedValue) {
let _ = context.engine.peers.updatePeerReactionSettings(peerId: peerId, reactionSettings: PeerReactionSettings(allowedReactions: updatedValue, maxReactionCount: 11)).start()
let _ = context.engine.peers.updatePeerReactionSettings(peerId: peerId, reactionSettings: PeerReactionSettings(allowedReactions: updatedValue, maxReactionCount: 11, starsAllowed: nil)).start()
}
})
}

View File

@ -69,6 +69,8 @@ public final class ReactionItem {
return .builtin(value)
case let .custom(fileId):
return .custom(fileId: fileId, file: self.listAnimation)
case .stars:
return .stars
}
}
}
@ -965,6 +967,8 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate {
break
case .custom:
loopIdle = true
case .stars:
break
}
}
}
@ -1668,6 +1672,8 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate {
updateReaction = .builtin(value)
case let .custom(fileId):
updateReaction = .custom(fileId: fileId, file: nil)
case .stars:
updateReaction = .stars
}
let reactionItem = ReactionItem(
@ -2604,7 +2610,7 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate {
}
}
public func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, forceSwitchToInlineImmediately: Bool = false, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, completion: @escaping () -> Void) {
public func animateOutToReaction(value: MessageReaction.Reaction, targetView: UIView, hideNode: Bool, forceSwitchToInlineImmediately: Bool = false, animateTargetContainer: UIView?, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, onHit: (() -> Void)?, completion: @escaping () -> Void) {
self.isAnimatingOutToReaction = true
var foundItemNode: ReactionNode?
@ -2639,6 +2645,8 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate {
switchToInlineImmediately = forceSwitchToInlineImmediately
case .custom:
switchToInlineImmediately = !self.didTriggerExpandedReaction
case .stars:
switchToInlineImmediately = forceSwitchToInlineImmediately
}
} else {
switchToInlineImmediately = !self.didTriggerExpandedReaction
@ -2853,6 +2861,7 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate {
strongSelf.hapticFeedback = HapticFeedback()
}
strongSelf.hapticFeedback?.tap()
onHit?()
if let targetView = targetView as? ReactionIconView {
if switchToInlineImmediately {
@ -3283,13 +3292,13 @@ public final class StandaloneReactionAnimation: ASDisplayNode {
self.isUserInteractionEnabled = false
}
public func animateReactionSelection(context: AccountContext, theme: PresentationTheme, animationCache: AnimationCache, reaction: ReactionItem, customEffectResource: MediaResource? = nil, avatarPeers: [EnginePeer], playHaptic: Bool, isLarge: Bool, playCenterReaction: Bool = true, forceSmallEffectAnimation: Bool = false, hideCenterAnimation: Bool = false, targetView: UIView, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, completion: @escaping () -> Void) {
self.animateReactionSelection(context: context, theme: theme, animationCache: animationCache, reaction: reaction, customEffectResource: customEffectResource, avatarPeers: avatarPeers, playHaptic: playHaptic, isLarge: isLarge, playCenterReaction: playCenterReaction, forceSmallEffectAnimation: forceSmallEffectAnimation, hideCenterAnimation: hideCenterAnimation, targetView: targetView, addStandaloneReactionAnimation: addStandaloneReactionAnimation, currentItemNode: nil, completion: completion)
public func animateReactionSelection(context: AccountContext, theme: PresentationTheme, animationCache: AnimationCache, reaction: ReactionItem, customEffectResource: MediaResource? = nil, avatarPeers: [EnginePeer], playHaptic: Bool, isLarge: Bool, playCenterReaction: Bool = true, forceSmallEffectAnimation: Bool = false, hideCenterAnimation: Bool = false, targetView: UIView, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, onHit: (() -> Void)? = nil, completion: @escaping () -> Void) {
self.animateReactionSelection(context: context, theme: theme, animationCache: animationCache, reaction: reaction, customEffectResource: customEffectResource, avatarPeers: avatarPeers, playHaptic: playHaptic, isLarge: isLarge, playCenterReaction: playCenterReaction, forceSmallEffectAnimation: forceSmallEffectAnimation, hideCenterAnimation: hideCenterAnimation, targetView: targetView, addStandaloneReactionAnimation: addStandaloneReactionAnimation, currentItemNode: nil, onHit: onHit, completion: completion)
}
public var currentDismissAnimation: (() -> Void)?
public func animateReactionSelection(context: AccountContext, theme: PresentationTheme, animationCache: AnimationCache, reaction: ReactionItem, customEffectResource: MediaResource? = nil, avatarPeers: [EnginePeer], playHaptic: Bool, isLarge: Bool, playCenterReaction: Bool = true, forceSmallEffectAnimation: Bool = false, hideCenterAnimation: Bool = false, targetView: UIView, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, currentItemNode: ReactionNode?, completion: @escaping () -> Void) {
public func animateReactionSelection(context: AccountContext, theme: PresentationTheme, animationCache: AnimationCache, reaction: ReactionItem, customEffectResource: MediaResource? = nil, avatarPeers: [EnginePeer], playHaptic: Bool, isLarge: Bool, playCenterReaction: Bool = true, forceSmallEffectAnimation: Bool = false, hideCenterAnimation: Bool = false, targetView: UIView, addStandaloneReactionAnimation: ((StandaloneReactionAnimation) -> Void)?, currentItemNode: ReactionNode?, onHit: (() -> Void)? = nil, completion: @escaping () -> Void) {
guard let sourceSnapshotView = targetView.snapshotContentTree() else {
completion()
return
@ -3298,6 +3307,7 @@ public final class StandaloneReactionAnimation: ASDisplayNode {
if playHaptic {
self.hapticFeedback.tap()
}
onHit?()
self.targetView = targetView
@ -3322,6 +3332,8 @@ public final class StandaloneReactionAnimation: ASDisplayNode {
switchToInlineImmediately = false
case .custom:
switchToInlineImmediately = true
case .stars:
switchToInlineImmediately = false
}
} else {
switchToInlineImmediately = false
@ -3708,12 +3720,16 @@ public final class StandaloneReactionAnimation: ASDisplayNode {
var selfTargetBounds = targetView.bounds
if let itemNode = self.itemNode, case .builtin = itemNode.item.reaction.rawValue {
selfTargetBounds = selfTargetBounds.insetBy(dx: -selfTargetBounds.width * 0.5, dy: -selfTargetBounds.height * 0.5)
} else if let itemNode = self.itemNode, case .stars = itemNode.item.reaction.rawValue {
selfTargetBounds = selfTargetBounds.insetBy(dx: -selfTargetBounds.width * 0.5, dy: -selfTargetBounds.height * 0.5)
}
var targetFrame = self.view.convert(targetView.convert(selfTargetBounds, to: nil), from: nil)
if let itemNode = self.itemNode, case .builtin = itemNode.item.reaction.rawValue {
targetFrame = targetFrame.insetBy(dx: -targetFrame.width * 0.5, dy: -targetFrame.height * 0.5)
} else if let itemNode = self.itemNode, case .stars = itemNode.item.reaction.rawValue {
targetFrame = targetFrame.insetBy(dx: -targetFrame.width * 0.5, dy: -targetFrame.height * 0.5)
}
targetSnapshotView.frame = targetFrame

View File

@ -60,7 +60,7 @@ private final class StarsReactionEffectLayer: SimpleLayer {
override init() {
super.init()
self.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2).cgColor
//self.backgroundColor = UIColor.lightGray.withAlphaComponent(0.2).cgColor
}
override init(layer: Any) {
@ -150,7 +150,7 @@ public final class ReactionNode: ASDisplayNode, ReactionItemNode {
super.init()
if case .custom(MessageReaction.starsReactionId) = item.reaction.rawValue {
if case .stars = item.reaction.rawValue {
let starsEffectLayer = StarsReactionEffectLayer()
self.starsEffectLayer = starsEffectLayer
self.layer.addSublayer(starsEffectLayer)

View File

@ -178,12 +178,12 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1078612597] = { return Api.ChannelLocation.parse_channelLocationEmpty($0) }
dict[-847783593] = { return Api.ChannelMessagesFilter.parse_channelMessagesFilter($0) }
dict[-1798033689] = { return Api.ChannelMessagesFilter.parse_channelMessagesFilterEmpty($0) }
dict[-1072953408] = { return Api.ChannelParticipant.parse_channelParticipant($0) }
dict[-885426663] = { return Api.ChannelParticipant.parse_channelParticipant($0) }
dict[885242707] = { return Api.ChannelParticipant.parse_channelParticipantAdmin($0) }
dict[1844969806] = { return Api.ChannelParticipant.parse_channelParticipantBanned($0) }
dict[803602899] = { return Api.ChannelParticipant.parse_channelParticipantCreator($0) }
dict[453242886] = { return Api.ChannelParticipant.parse_channelParticipantLeft($0) }
dict[900251559] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) }
dict[1331723247] = { return Api.ChannelParticipant.parse_channelParticipantSelf($0) }
dict[-1268741783] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsAdmins($0) }
dict[338142689] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsBanned($0) }
dict[-1328445861] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsBots($0) }
@ -192,7 +192,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-531931925] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsMentions($0) }
dict[-566281095] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsRecent($0) }
dict[106343499] = { return Api.ChannelParticipantsFilter.parse_channelParticipantsSearch($0) }
dict[179174543] = { return Api.Chat.parse_channel($0) }
dict[-29067075] = { return Api.Chat.parse_channel($0) }
dict[399807445] = { return Api.Chat.parse_channelForbidden($0) }
dict[1103884886] = { return Api.Chat.parse_chat($0) }
dict[693512293] = { return Api.Chat.parse_chatEmpty($0) }
@ -202,7 +202,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
dict[-1146407795] = { return Api.ChatFull.parse_channelFull($0) }
dict[640893467] = { return Api.ChatFull.parse_chatFull($0) }
dict[-840897472] = { return Api.ChatInvite.parse_chatInvite($0) }
dict[-26920803] = { return Api.ChatInvite.parse_chatInvite($0) }
dict[1516793212] = { return Api.ChatInvite.parse_chatInviteAlready($0) }
dict[1634294960] = { return Api.ChatInvite.parse_chatInvitePeek($0) }
dict[-1940201511] = { return Api.ChatInviteImporter.parse_chatInviteImporter($0) }
@ -274,7 +274,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1038136962] = { return Api.EncryptedFile.parse_encryptedFileEmpty($0) }
dict[-317144808] = { return Api.EncryptedMessage.parse_encryptedMessage($0) }
dict[594758406] = { return Api.EncryptedMessage.parse_encryptedMessageService($0) }
dict[179611673] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
dict[-1812799720] = { return Api.ExportedChatInvite.parse_chatInviteExported($0) }
dict[-317687113] = { return Api.ExportedChatInvite.parse_chatInvitePublicJoinRequests($0) }
dict[206668204] = { return Api.ExportedChatlistInvite.parse_exportedChatlistInvite($0) }
dict[1103040667] = { return Api.ExportedContactToken.parse_exportedContactToken($0) }
@ -372,6 +372,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1210199983] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) }
dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) }
dict[-659913713] = { return Api.InputGroupCall.parse_inputGroupCall($0) }
dict[887591921] = { return Api.InputInvoice.parse_inputInvoiceChatInviteSubscription($0) }
dict[-977967015] = { return Api.InputInvoice.parse_inputInvoiceMessage($0) }
dict[-1734841331] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftCode($0) }
dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) }
@ -618,7 +619,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1959634180] = { return Api.MessagePeerVote.parse_messagePeerVoteInputOption($0) }
dict[1177089766] = { return Api.MessagePeerVote.parse_messagePeerVoteMultiple($0) }
dict[182649427] = { return Api.MessageRange.parse_messageRange($0) }
dict[1328256121] = { return Api.MessageReactions.parse_messageReactions($0) }
dict[171155211] = { return Api.MessageReactions.parse_messageReactions($0) }
dict[-285158328] = { return Api.MessageReactor.parse_messageReactor($0) }
dict[-2083123262] = { return Api.MessageReplies.parse_messageReplies($0) }
dict[-1346631205] = { return Api.MessageReplyHeader.parse_messageReplyHeader($0) }
dict[240843065] = { return Api.MessageReplyHeader.parse_messageReplyStoryHeader($0) }
@ -767,6 +769,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1992950669] = { return Api.Reaction.parse_reactionCustomEmoji($0) }
dict[455247544] = { return Api.Reaction.parse_reactionEmoji($0) }
dict[2046153753] = { return Api.Reaction.parse_reactionEmpty($0) }
dict[1379771627] = { return Api.Reaction.parse_reactionPaid($0) }
dict[-1546531968] = { return Api.ReactionCount.parse_reactionCount($0) }
dict[1268654752] = { return Api.ReactionNotificationsFrom.parse_reactionNotificationsFromAll($0) }
dict[-1161583078] = { return Api.ReactionNotificationsFrom.parse_reactionNotificationsFromContacts($0) }
@ -881,8 +884,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
dict[1577421297] = { return Api.StarsGiftOption.parse_starsGiftOption($0) }
dict[2033461574] = { return Api.StarsRevenueStatus.parse_starsRevenueStatus($0) }
dict[-797707802] = { return Api.StarsSubscription.parse_starsSubscription($0) }
dict[88173912] = { return Api.StarsSubscriptionPricing.parse_starsSubscriptionPricing($0) }
dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) }
dict[766853519] = { return Api.StarsTransaction.parse_starsTransaction($0) }
dict[1127934763] = { return Api.StarsTransaction.parse_starsTransaction($0) }
dict[-670195363] = { return Api.StarsTransactionPeer.parse_starsTransactionPeer($0) }
dict[1617438738] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAds($0) }
dict[-1269320843] = { return Api.StarsTransactionPeer.parse_starsTransactionPeerAppStore($0) }
@ -1327,7 +1332,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[961445665] = { return Api.payments.StarsRevenueAdsAccountUrl.parse_starsRevenueAdsAccountUrl($0) }
dict[-919881925] = { return Api.payments.StarsRevenueStats.parse_starsRevenueStats($0) }
dict[497778871] = { return Api.payments.StarsRevenueWithdrawalUrl.parse_starsRevenueWithdrawalUrl($0) }
dict[-1930105248] = { return Api.payments.StarsStatus.parse_starsStatus($0) }
dict[-1141231252] = { return Api.payments.StarsStatus.parse_starsStatus($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
dict[541839704] = { return Api.phone.ExportedGroupCallInvite.parse_exportedGroupCallInvite($0) }
dict[-1636664659] = { return Api.phone.GroupCall.parse_groupCall($0) }
@ -1402,7 +1407,7 @@ public extension Api {
return parser(reader)
}
else {
telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found")
telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found")
return nil
}
}
@ -1824,6 +1829,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.MessageReactions:
_1.serialize(buffer, boxed)
case let _1 as Api.MessageReactor:
_1.serialize(buffer, boxed)
case let _1 as Api.MessageReplies:
_1.serialize(buffer, boxed)
case let _1 as Api.MessageReplyHeader:
@ -2000,6 +2007,10 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.StarsRevenueStatus:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsSubscription:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsSubscriptionPricing:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsTopupOption:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsTransaction:

View File

@ -1,5 +1,6 @@
public extension Api {
indirect enum InputInvoice: TypeConstructorDescription {
case inputInvoiceChatInviteSubscription(hash: String)
case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32)
case inputInvoicePremiumGiftCode(purpose: Api.InputStorePaymentPurpose, option: Api.PremiumGiftCodeOption)
case inputInvoiceSlug(slug: String)
@ -7,6 +8,12 @@ public extension Api {
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputInvoiceChatInviteSubscription(let hash):
if boxed {
buffer.appendInt32(887591921)
}
serializeString(hash, buffer: buffer, boxed: false)
break
case .inputInvoiceMessage(let peer, let msgId):
if boxed {
buffer.appendInt32(-977967015)
@ -38,6 +45,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputInvoiceChatInviteSubscription(let hash):
return ("inputInvoiceChatInviteSubscription", [("hash", hash as Any)])
case .inputInvoiceMessage(let peer, let msgId):
return ("inputInvoiceMessage", [("peer", peer as Any), ("msgId", msgId as Any)])
case .inputInvoicePremiumGiftCode(let purpose, let option):
@ -49,6 +58,17 @@ public extension Api {
}
}
public static func parse_inputInvoiceChatInviteSubscription(_ reader: BufferReader) -> InputInvoice? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.InputInvoice.inputInvoiceChatInviteSubscription(hash: _1!)
}
else {
return nil
}
}
public static func parse_inputInvoiceMessage(_ reader: BufferReader) -> InputInvoice? {
var _1: Api.InputPeer?
if let signature = reader.readInt32() {
@ -920,113 +940,3 @@ public extension Api {
}
}
public extension Api {
enum InputPaymentCredentials: TypeConstructorDescription {
case inputPaymentCredentials(flags: Int32, data: Api.DataJSON)
case inputPaymentCredentialsApplePay(paymentData: Api.DataJSON)
case inputPaymentCredentialsGooglePay(paymentToken: Api.DataJSON)
case inputPaymentCredentialsSaved(id: String, tmpPassword: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPaymentCredentials(let flags, let data):
if boxed {
buffer.appendInt32(873977640)
}
serializeInt32(flags, buffer: buffer, boxed: false)
data.serialize(buffer, true)
break
case .inputPaymentCredentialsApplePay(let paymentData):
if boxed {
buffer.appendInt32(178373535)
}
paymentData.serialize(buffer, true)
break
case .inputPaymentCredentialsGooglePay(let paymentToken):
if boxed {
buffer.appendInt32(-1966921727)
}
paymentToken.serialize(buffer, true)
break
case .inputPaymentCredentialsSaved(let id, let tmpPassword):
if boxed {
buffer.appendInt32(-1056001329)
}
serializeString(id, buffer: buffer, boxed: false)
serializeBytes(tmpPassword, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPaymentCredentials(let flags, let data):
return ("inputPaymentCredentials", [("flags", flags as Any), ("data", data as Any)])
case .inputPaymentCredentialsApplePay(let paymentData):
return ("inputPaymentCredentialsApplePay", [("paymentData", paymentData as Any)])
case .inputPaymentCredentialsGooglePay(let paymentToken):
return ("inputPaymentCredentialsGooglePay", [("paymentToken", paymentToken as Any)])
case .inputPaymentCredentialsSaved(let id, let tmpPassword):
return ("inputPaymentCredentialsSaved", [("id", id as Any), ("tmpPassword", tmpPassword as Any)])
}
}
public static func parse_inputPaymentCredentials(_ reader: BufferReader) -> InputPaymentCredentials? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.DataJSON?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputPaymentCredentials.inputPaymentCredentials(flags: _1!, data: _2!)
}
else {
return nil
}
}
public static func parse_inputPaymentCredentialsApplePay(_ reader: BufferReader) -> InputPaymentCredentials? {
var _1: Api.DataJSON?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPaymentCredentials.inputPaymentCredentialsApplePay(paymentData: _1!)
}
else {
return nil
}
}
public static func parse_inputPaymentCredentialsGooglePay(_ reader: BufferReader) -> InputPaymentCredentials? {
var _1: Api.DataJSON?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPaymentCredentials.inputPaymentCredentialsGooglePay(paymentToken: _1!)
}
else {
return nil
}
}
public static func parse_inputPaymentCredentialsSaved(_ reader: BufferReader) -> InputPaymentCredentials? {
var _1: String?
_1 = parseString(reader)
var _2: Buffer?
_2 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputPaymentCredentials.inputPaymentCredentialsSaved(id: _1!, tmpPassword: _2!)
}
else {
return nil
}
}
}
}

View File

@ -1,3 +1,113 @@
public extension Api {
enum InputPaymentCredentials: TypeConstructorDescription {
case inputPaymentCredentials(flags: Int32, data: Api.DataJSON)
case inputPaymentCredentialsApplePay(paymentData: Api.DataJSON)
case inputPaymentCredentialsGooglePay(paymentToken: Api.DataJSON)
case inputPaymentCredentialsSaved(id: String, tmpPassword: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPaymentCredentials(let flags, let data):
if boxed {
buffer.appendInt32(873977640)
}
serializeInt32(flags, buffer: buffer, boxed: false)
data.serialize(buffer, true)
break
case .inputPaymentCredentialsApplePay(let paymentData):
if boxed {
buffer.appendInt32(178373535)
}
paymentData.serialize(buffer, true)
break
case .inputPaymentCredentialsGooglePay(let paymentToken):
if boxed {
buffer.appendInt32(-1966921727)
}
paymentToken.serialize(buffer, true)
break
case .inputPaymentCredentialsSaved(let id, let tmpPassword):
if boxed {
buffer.appendInt32(-1056001329)
}
serializeString(id, buffer: buffer, boxed: false)
serializeBytes(tmpPassword, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPaymentCredentials(let flags, let data):
return ("inputPaymentCredentials", [("flags", flags as Any), ("data", data as Any)])
case .inputPaymentCredentialsApplePay(let paymentData):
return ("inputPaymentCredentialsApplePay", [("paymentData", paymentData as Any)])
case .inputPaymentCredentialsGooglePay(let paymentToken):
return ("inputPaymentCredentialsGooglePay", [("paymentToken", paymentToken as Any)])
case .inputPaymentCredentialsSaved(let id, let tmpPassword):
return ("inputPaymentCredentialsSaved", [("id", id as Any), ("tmpPassword", tmpPassword as Any)])
}
}
public static func parse_inputPaymentCredentials(_ reader: BufferReader) -> InputPaymentCredentials? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.DataJSON?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputPaymentCredentials.inputPaymentCredentials(flags: _1!, data: _2!)
}
else {
return nil
}
}
public static func parse_inputPaymentCredentialsApplePay(_ reader: BufferReader) -> InputPaymentCredentials? {
var _1: Api.DataJSON?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPaymentCredentials.inputPaymentCredentialsApplePay(paymentData: _1!)
}
else {
return nil
}
}
public static func parse_inputPaymentCredentialsGooglePay(_ reader: BufferReader) -> InputPaymentCredentials? {
var _1: Api.DataJSON?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPaymentCredentials.inputPaymentCredentialsGooglePay(paymentToken: _1!)
}
else {
return nil
}
}
public static func parse_inputPaymentCredentialsSaved(_ reader: BufferReader) -> InputPaymentCredentials? {
var _1: String?
_1 = parseString(reader)
var _2: Buffer?
_2 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputPaymentCredentials.inputPaymentCredentialsSaved(id: _1!, tmpPassword: _2!)
}
else {
return nil
}
}
}
}
public extension Api {
indirect enum InputPeer: TypeConstructorDescription {
case inputPeerChannel(channelId: Int64, accessHash: Int64)

View File

@ -200,13 +200,13 @@ public extension Api {
}
public extension Api {
enum MessageReactions: TypeConstructorDescription {
case messageReactions(flags: Int32, results: [Api.ReactionCount], recentReactions: [Api.MessagePeerReaction]?)
case messageReactions(flags: Int32, results: [Api.ReactionCount], recentReactions: [Api.MessagePeerReaction]?, topReactors: [Api.MessageReactor]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .messageReactions(let flags, let results, let recentReactions):
case .messageReactions(let flags, let results, let recentReactions, let topReactors):
if boxed {
buffer.appendInt32(1328256121)
buffer.appendInt32(171155211)
}
serializeInt32(flags, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
@ -219,14 +219,19 @@ public extension Api {
for item in recentReactions! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 4) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(topReactors!.count))
for item in topReactors! {
item.serialize(buffer, true)
}}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .messageReactions(let flags, let results, let recentReactions):
return ("messageReactions", [("flags", flags as Any), ("results", results as Any), ("recentReactions", recentReactions as Any)])
case .messageReactions(let flags, let results, let recentReactions, let topReactors):
return ("messageReactions", [("flags", flags as Any), ("results", results as Any), ("recentReactions", recentReactions as Any), ("topReactors", topReactors as Any)])
}
}
@ -241,11 +246,62 @@ public extension Api {
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessagePeerReaction.self)
} }
var _4: [Api.MessageReactor]?
if Int(_1!) & Int(1 << 4) != 0 {if let _ = reader.readInt32() {
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageReactor.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.MessageReactions.messageReactions(flags: _1!, results: _2!, recentReactions: _3, topReactors: _4)
}
else {
return nil
}
}
}
}
public extension Api {
enum MessageReactor: TypeConstructorDescription {
case messageReactor(flags: Int32, peerId: Api.Peer, count: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .messageReactor(let flags, let peerId, let count):
if boxed {
buffer.appendInt32(-285158328)
}
serializeInt32(flags, buffer: buffer, boxed: false)
peerId.serialize(buffer, true)
serializeInt32(count, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .messageReactor(let flags, let peerId, let count):
return ("messageReactor", [("flags", flags as Any), ("peerId", peerId as Any), ("count", count as Any)])
}
}
public static func parse_messageReactor(_ reader: BufferReader) -> MessageReactor? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Peer?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.MessageReactions.messageReactions(flags: _1!, results: _2!, recentReactions: _3)
return Api.MessageReactor.messageReactor(flags: _1!, peerId: _2!, count: _3!)
}
else {
return nil

View File

@ -309,6 +309,7 @@ public extension Api {
case reactionCustomEmoji(documentId: Int64)
case reactionEmoji(emoticon: String)
case reactionEmpty
case reactionPaid
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
@ -329,6 +330,12 @@ public extension Api {
buffer.appendInt32(2046153753)
}
break
case .reactionPaid:
if boxed {
buffer.appendInt32(1379771627)
}
break
}
}
@ -341,6 +348,8 @@ public extension Api {
return ("reactionEmoji", [("emoticon", emoticon as Any)])
case .reactionEmpty:
return ("reactionEmpty", [])
case .reactionPaid:
return ("reactionPaid", [])
}
}
@ -369,6 +378,9 @@ public extension Api {
public static func parse_reactionEmpty(_ reader: BufferReader) -> Reaction? {
return Api.Reaction.reactionEmpty
}
public static func parse_reactionPaid(_ reader: BufferReader) -> Reaction? {
return Api.Reaction.reactionPaid
}
}
}
@ -858,139 +870,3 @@ public extension Api {
}
}
public extension Api {
enum ReportReason: TypeConstructorDescription {
case inputReportReasonChildAbuse
case inputReportReasonCopyright
case inputReportReasonFake
case inputReportReasonGeoIrrelevant
case inputReportReasonIllegalDrugs
case inputReportReasonOther
case inputReportReasonPersonalDetails
case inputReportReasonPornography
case inputReportReasonSpam
case inputReportReasonViolence
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputReportReasonChildAbuse:
if boxed {
buffer.appendInt32(-1376497949)
}
break
case .inputReportReasonCopyright:
if boxed {
buffer.appendInt32(-1685456582)
}
break
case .inputReportReasonFake:
if boxed {
buffer.appendInt32(-170010905)
}
break
case .inputReportReasonGeoIrrelevant:
if boxed {
buffer.appendInt32(-606798099)
}
break
case .inputReportReasonIllegalDrugs:
if boxed {
buffer.appendInt32(177124030)
}
break
case .inputReportReasonOther:
if boxed {
buffer.appendInt32(-1041980751)
}
break
case .inputReportReasonPersonalDetails:
if boxed {
buffer.appendInt32(-1631091139)
}
break
case .inputReportReasonPornography:
if boxed {
buffer.appendInt32(777640226)
}
break
case .inputReportReasonSpam:
if boxed {
buffer.appendInt32(1490799288)
}
break
case .inputReportReasonViolence:
if boxed {
buffer.appendInt32(505595789)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputReportReasonChildAbuse:
return ("inputReportReasonChildAbuse", [])
case .inputReportReasonCopyright:
return ("inputReportReasonCopyright", [])
case .inputReportReasonFake:
return ("inputReportReasonFake", [])
case .inputReportReasonGeoIrrelevant:
return ("inputReportReasonGeoIrrelevant", [])
case .inputReportReasonIllegalDrugs:
return ("inputReportReasonIllegalDrugs", [])
case .inputReportReasonOther:
return ("inputReportReasonOther", [])
case .inputReportReasonPersonalDetails:
return ("inputReportReasonPersonalDetails", [])
case .inputReportReasonPornography:
return ("inputReportReasonPornography", [])
case .inputReportReasonSpam:
return ("inputReportReasonSpam", [])
case .inputReportReasonViolence:
return ("inputReportReasonViolence", [])
}
}
public static func parse_inputReportReasonChildAbuse(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonChildAbuse
}
public static func parse_inputReportReasonCopyright(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonCopyright
}
public static func parse_inputReportReasonFake(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonFake
}
public static func parse_inputReportReasonGeoIrrelevant(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonGeoIrrelevant
}
public static func parse_inputReportReasonIllegalDrugs(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonIllegalDrugs
}
public static func parse_inputReportReasonOther(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonOther
}
public static func parse_inputReportReasonPersonalDetails(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonPersonalDetails
}
public static func parse_inputReportReasonPornography(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonPornography
}
public static func parse_inputReportReasonSpam(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonSpam
}
public static func parse_inputReportReasonViolence(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonViolence
}
}
}

View File

@ -1,3 +1,139 @@
public extension Api {
enum ReportReason: TypeConstructorDescription {
case inputReportReasonChildAbuse
case inputReportReasonCopyright
case inputReportReasonFake
case inputReportReasonGeoIrrelevant
case inputReportReasonIllegalDrugs
case inputReportReasonOther
case inputReportReasonPersonalDetails
case inputReportReasonPornography
case inputReportReasonSpam
case inputReportReasonViolence
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputReportReasonChildAbuse:
if boxed {
buffer.appendInt32(-1376497949)
}
break
case .inputReportReasonCopyright:
if boxed {
buffer.appendInt32(-1685456582)
}
break
case .inputReportReasonFake:
if boxed {
buffer.appendInt32(-170010905)
}
break
case .inputReportReasonGeoIrrelevant:
if boxed {
buffer.appendInt32(-606798099)
}
break
case .inputReportReasonIllegalDrugs:
if boxed {
buffer.appendInt32(177124030)
}
break
case .inputReportReasonOther:
if boxed {
buffer.appendInt32(-1041980751)
}
break
case .inputReportReasonPersonalDetails:
if boxed {
buffer.appendInt32(-1631091139)
}
break
case .inputReportReasonPornography:
if boxed {
buffer.appendInt32(777640226)
}
break
case .inputReportReasonSpam:
if boxed {
buffer.appendInt32(1490799288)
}
break
case .inputReportReasonViolence:
if boxed {
buffer.appendInt32(505595789)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputReportReasonChildAbuse:
return ("inputReportReasonChildAbuse", [])
case .inputReportReasonCopyright:
return ("inputReportReasonCopyright", [])
case .inputReportReasonFake:
return ("inputReportReasonFake", [])
case .inputReportReasonGeoIrrelevant:
return ("inputReportReasonGeoIrrelevant", [])
case .inputReportReasonIllegalDrugs:
return ("inputReportReasonIllegalDrugs", [])
case .inputReportReasonOther:
return ("inputReportReasonOther", [])
case .inputReportReasonPersonalDetails:
return ("inputReportReasonPersonalDetails", [])
case .inputReportReasonPornography:
return ("inputReportReasonPornography", [])
case .inputReportReasonSpam:
return ("inputReportReasonSpam", [])
case .inputReportReasonViolence:
return ("inputReportReasonViolence", [])
}
}
public static func parse_inputReportReasonChildAbuse(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonChildAbuse
}
public static func parse_inputReportReasonCopyright(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonCopyright
}
public static func parse_inputReportReasonFake(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonFake
}
public static func parse_inputReportReasonGeoIrrelevant(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonGeoIrrelevant
}
public static func parse_inputReportReasonIllegalDrugs(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonIllegalDrugs
}
public static func parse_inputReportReasonOther(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonOther
}
public static func parse_inputReportReasonPersonalDetails(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonPersonalDetails
}
public static func parse_inputReportReasonPornography(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonPornography
}
public static func parse_inputReportReasonSpam(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonSpam
}
public static func parse_inputReportReasonViolence(_ reader: BufferReader) -> ReportReason? {
return Api.ReportReason.inputReportReasonViolence
}
}
}
public extension Api {
enum RequestPeerType: TypeConstructorDescription {
case requestPeerTypeBroadcast(flags: Int32, hasUsername: Api.Bool?, userAdminRights: Api.ChatAdminRights?, botAdminRights: Api.ChatAdminRights?)
@ -688,399 +824,3 @@ public extension Api {
}
}
public extension Api {
enum SavedContact: TypeConstructorDescription {
case savedPhoneContact(phone: String, firstName: String, lastName: String, date: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedPhoneContact(let phone, let firstName, let lastName, let date):
if boxed {
buffer.appendInt32(289586518)
}
serializeString(phone, buffer: buffer, boxed: false)
serializeString(firstName, buffer: buffer, boxed: false)
serializeString(lastName, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedPhoneContact(let phone, let firstName, let lastName, let date):
return ("savedPhoneContact", [("phone", phone as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("date", date as Any)])
}
}
public static func parse_savedPhoneContact(_ reader: BufferReader) -> SavedContact? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.SavedContact.savedPhoneContact(phone: _1!, firstName: _2!, lastName: _3!, date: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SavedDialog: TypeConstructorDescription {
case savedDialog(flags: Int32, peer: Api.Peer, topMessage: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedDialog(let flags, let peer, let topMessage):
if boxed {
buffer.appendInt32(-1115174036)
}
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt32(topMessage, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedDialog(let flags, let peer, let topMessage):
return ("savedDialog", [("flags", flags as Any), ("peer", peer as Any), ("topMessage", topMessage as Any)])
}
}
public static func parse_savedDialog(_ reader: BufferReader) -> SavedDialog? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Peer?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.SavedDialog.savedDialog(flags: _1!, peer: _2!, topMessage: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SavedReactionTag: TypeConstructorDescription {
case savedReactionTag(flags: Int32, reaction: Api.Reaction, title: String?, count: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedReactionTag(let flags, let reaction, let title, let count):
if boxed {
buffer.appendInt32(-881854424)
}
serializeInt32(flags, buffer: buffer, boxed: false)
reaction.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
serializeInt32(count, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedReactionTag(let flags, let reaction, let title, let count):
return ("savedReactionTag", [("flags", flags as Any), ("reaction", reaction as Any), ("title", title as Any), ("count", count as Any)])
}
}
public static func parse_savedReactionTag(_ reader: BufferReader) -> SavedReactionTag? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Reaction?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Reaction
}
var _3: String?
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.SavedReactionTag.savedReactionTag(flags: _1!, reaction: _2!, title: _3, count: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SearchResultsCalendarPeriod: TypeConstructorDescription {
case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count):
if boxed {
buffer.appendInt32(-911191137)
}
serializeInt32(date, buffer: buffer, boxed: false)
serializeInt32(minMsgId, buffer: buffer, boxed: false)
serializeInt32(maxMsgId, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count):
return ("searchResultsCalendarPeriod", [("date", date as Any), ("minMsgId", minMsgId as Any), ("maxMsgId", maxMsgId as Any), ("count", count as Any)])
}
}
public static func parse_searchResultsCalendarPeriod(_ reader: BufferReader) -> SearchResultsCalendarPeriod? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.SearchResultsCalendarPeriod.searchResultsCalendarPeriod(date: _1!, minMsgId: _2!, maxMsgId: _3!, count: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SearchResultsPosition: TypeConstructorDescription {
case searchResultPosition(msgId: Int32, date: Int32, offset: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchResultPosition(let msgId, let date, let offset):
if boxed {
buffer.appendInt32(2137295719)
}
serializeInt32(msgId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeInt32(offset, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchResultPosition(let msgId, let date, let offset):
return ("searchResultPosition", [("msgId", msgId as Any), ("date", date as Any), ("offset", offset as Any)])
}
}
public static func parse_searchResultPosition(_ reader: BufferReader) -> SearchResultsPosition? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.SearchResultsPosition.searchResultPosition(msgId: _1!, date: _2!, offset: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SecureCredentialsEncrypted: TypeConstructorDescription {
case secureCredentialsEncrypted(data: Buffer, hash: Buffer, secret: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .secureCredentialsEncrypted(let data, let hash, let secret):
if boxed {
buffer.appendInt32(871426631)
}
serializeBytes(data, buffer: buffer, boxed: false)
serializeBytes(hash, buffer: buffer, boxed: false)
serializeBytes(secret, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .secureCredentialsEncrypted(let data, let hash, let secret):
return ("secureCredentialsEncrypted", [("data", data as Any), ("hash", hash as Any), ("secret", secret as Any)])
}
}
public static func parse_secureCredentialsEncrypted(_ reader: BufferReader) -> SecureCredentialsEncrypted? {
var _1: Buffer?
_1 = parseBytes(reader)
var _2: Buffer?
_2 = parseBytes(reader)
var _3: Buffer?
_3 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.SecureCredentialsEncrypted.secureCredentialsEncrypted(data: _1!, hash: _2!, secret: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SecureData: TypeConstructorDescription {
case secureData(data: Buffer, dataHash: Buffer, secret: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .secureData(let data, let dataHash, let secret):
if boxed {
buffer.appendInt32(-1964327229)
}
serializeBytes(data, buffer: buffer, boxed: false)
serializeBytes(dataHash, buffer: buffer, boxed: false)
serializeBytes(secret, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .secureData(let data, let dataHash, let secret):
return ("secureData", [("data", data as Any), ("dataHash", dataHash as Any), ("secret", secret as Any)])
}
}
public static func parse_secureData(_ reader: BufferReader) -> SecureData? {
var _1: Buffer?
_1 = parseBytes(reader)
var _2: Buffer?
_2 = parseBytes(reader)
var _3: Buffer?
_3 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.SecureData.secureData(data: _1!, dataHash: _2!, secret: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SecureFile: TypeConstructorDescription {
case secureFile(id: Int64, accessHash: Int64, size: Int64, dcId: Int32, date: Int32, fileHash: Buffer, secret: Buffer)
case secureFileEmpty
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret):
if boxed {
buffer.appendInt32(2097791614)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeInt64(size, buffer: buffer, boxed: false)
serializeInt32(dcId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeBytes(fileHash, buffer: buffer, boxed: false)
serializeBytes(secret, buffer: buffer, boxed: false)
break
case .secureFileEmpty:
if boxed {
buffer.appendInt32(1679398724)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret):
return ("secureFile", [("id", id as Any), ("accessHash", accessHash as Any), ("size", size as Any), ("dcId", dcId as Any), ("date", date as Any), ("fileHash", fileHash as Any), ("secret", secret as Any)])
case .secureFileEmpty:
return ("secureFileEmpty", [])
}
}
public static func parse_secureFile(_ reader: BufferReader) -> SecureFile? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int64?
_3 = reader.readInt64()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
_5 = reader.readInt32()
var _6: Buffer?
_6 = parseBytes(reader)
var _7: Buffer?
_7 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.SecureFile.secureFile(id: _1!, accessHash: _2!, size: _3!, dcId: _4!, date: _5!, fileHash: _6!, secret: _7!)
}
else {
return nil
}
}
public static func parse_secureFileEmpty(_ reader: BufferReader) -> SecureFile? {
return Api.SecureFile.secureFileEmpty
}
}
}

View File

@ -1,3 +1,399 @@
public extension Api {
enum SavedContact: TypeConstructorDescription {
case savedPhoneContact(phone: String, firstName: String, lastName: String, date: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedPhoneContact(let phone, let firstName, let lastName, let date):
if boxed {
buffer.appendInt32(289586518)
}
serializeString(phone, buffer: buffer, boxed: false)
serializeString(firstName, buffer: buffer, boxed: false)
serializeString(lastName, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedPhoneContact(let phone, let firstName, let lastName, let date):
return ("savedPhoneContact", [("phone", phone as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("date", date as Any)])
}
}
public static func parse_savedPhoneContact(_ reader: BufferReader) -> SavedContact? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.SavedContact.savedPhoneContact(phone: _1!, firstName: _2!, lastName: _3!, date: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SavedDialog: TypeConstructorDescription {
case savedDialog(flags: Int32, peer: Api.Peer, topMessage: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedDialog(let flags, let peer, let topMessage):
if boxed {
buffer.appendInt32(-1115174036)
}
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt32(topMessage, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedDialog(let flags, let peer, let topMessage):
return ("savedDialog", [("flags", flags as Any), ("peer", peer as Any), ("topMessage", topMessage as Any)])
}
}
public static func parse_savedDialog(_ reader: BufferReader) -> SavedDialog? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Peer?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.SavedDialog.savedDialog(flags: _1!, peer: _2!, topMessage: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SavedReactionTag: TypeConstructorDescription {
case savedReactionTag(flags: Int32, reaction: Api.Reaction, title: String?, count: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .savedReactionTag(let flags, let reaction, let title, let count):
if boxed {
buffer.appendInt32(-881854424)
}
serializeInt32(flags, buffer: buffer, boxed: false)
reaction.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
serializeInt32(count, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .savedReactionTag(let flags, let reaction, let title, let count):
return ("savedReactionTag", [("flags", flags as Any), ("reaction", reaction as Any), ("title", title as Any), ("count", count as Any)])
}
}
public static func parse_savedReactionTag(_ reader: BufferReader) -> SavedReactionTag? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Reaction?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Reaction
}
var _3: String?
if Int(_1!) & Int(1 << 0) != 0 {_3 = parseString(reader) }
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.SavedReactionTag.savedReactionTag(flags: _1!, reaction: _2!, title: _3, count: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SearchResultsCalendarPeriod: TypeConstructorDescription {
case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count):
if boxed {
buffer.appendInt32(-911191137)
}
serializeInt32(date, buffer: buffer, boxed: false)
serializeInt32(minMsgId, buffer: buffer, boxed: false)
serializeInt32(maxMsgId, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count):
return ("searchResultsCalendarPeriod", [("date", date as Any), ("minMsgId", minMsgId as Any), ("maxMsgId", maxMsgId as Any), ("count", count as Any)])
}
}
public static func parse_searchResultsCalendarPeriod(_ reader: BufferReader) -> SearchResultsCalendarPeriod? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
_4 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.SearchResultsCalendarPeriod.searchResultsCalendarPeriod(date: _1!, minMsgId: _2!, maxMsgId: _3!, count: _4!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SearchResultsPosition: TypeConstructorDescription {
case searchResultPosition(msgId: Int32, date: Int32, offset: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .searchResultPosition(let msgId, let date, let offset):
if boxed {
buffer.appendInt32(2137295719)
}
serializeInt32(msgId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeInt32(offset, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .searchResultPosition(let msgId, let date, let offset):
return ("searchResultPosition", [("msgId", msgId as Any), ("date", date as Any), ("offset", offset as Any)])
}
}
public static func parse_searchResultPosition(_ reader: BufferReader) -> SearchResultsPosition? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int32?
_2 = reader.readInt32()
var _3: Int32?
_3 = reader.readInt32()
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.SearchResultsPosition.searchResultPosition(msgId: _1!, date: _2!, offset: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SecureCredentialsEncrypted: TypeConstructorDescription {
case secureCredentialsEncrypted(data: Buffer, hash: Buffer, secret: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .secureCredentialsEncrypted(let data, let hash, let secret):
if boxed {
buffer.appendInt32(871426631)
}
serializeBytes(data, buffer: buffer, boxed: false)
serializeBytes(hash, buffer: buffer, boxed: false)
serializeBytes(secret, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .secureCredentialsEncrypted(let data, let hash, let secret):
return ("secureCredentialsEncrypted", [("data", data as Any), ("hash", hash as Any), ("secret", secret as Any)])
}
}
public static func parse_secureCredentialsEncrypted(_ reader: BufferReader) -> SecureCredentialsEncrypted? {
var _1: Buffer?
_1 = parseBytes(reader)
var _2: Buffer?
_2 = parseBytes(reader)
var _3: Buffer?
_3 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.SecureCredentialsEncrypted.secureCredentialsEncrypted(data: _1!, hash: _2!, secret: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SecureData: TypeConstructorDescription {
case secureData(data: Buffer, dataHash: Buffer, secret: Buffer)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .secureData(let data, let dataHash, let secret):
if boxed {
buffer.appendInt32(-1964327229)
}
serializeBytes(data, buffer: buffer, boxed: false)
serializeBytes(dataHash, buffer: buffer, boxed: false)
serializeBytes(secret, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .secureData(let data, let dataHash, let secret):
return ("secureData", [("data", data as Any), ("dataHash", dataHash as Any), ("secret", secret as Any)])
}
}
public static func parse_secureData(_ reader: BufferReader) -> SecureData? {
var _1: Buffer?
_1 = parseBytes(reader)
var _2: Buffer?
_2 = parseBytes(reader)
var _3: Buffer?
_3 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.SecureData.secureData(data: _1!, dataHash: _2!, secret: _3!)
}
else {
return nil
}
}
}
}
public extension Api {
enum SecureFile: TypeConstructorDescription {
case secureFile(id: Int64, accessHash: Int64, size: Int64, dcId: Int32, date: Int32, fileHash: Buffer, secret: Buffer)
case secureFileEmpty
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret):
if boxed {
buffer.appendInt32(2097791614)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeInt64(size, buffer: buffer, boxed: false)
serializeInt32(dcId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
serializeBytes(fileHash, buffer: buffer, boxed: false)
serializeBytes(secret, buffer: buffer, boxed: false)
break
case .secureFileEmpty:
if boxed {
buffer.appendInt32(1679398724)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .secureFile(let id, let accessHash, let size, let dcId, let date, let fileHash, let secret):
return ("secureFile", [("id", id as Any), ("accessHash", accessHash as Any), ("size", size as Any), ("dcId", dcId as Any), ("date", date as Any), ("fileHash", fileHash as Any), ("secret", secret as Any)])
case .secureFileEmpty:
return ("secureFileEmpty", [])
}
}
public static func parse_secureFile(_ reader: BufferReader) -> SecureFile? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int64?
_3 = reader.readInt64()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
_5 = reader.readInt32()
var _6: Buffer?
_6 = parseBytes(reader)
var _7: Buffer?
_7 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.SecureFile.secureFile(id: _1!, accessHash: _2!, size: _3!, dcId: _4!, date: _5!, fileHash: _6!, secret: _7!)
}
else {
return nil
}
}
public static func parse_secureFileEmpty(_ reader: BufferReader) -> SecureFile? {
return Api.SecureFile.secureFileEmpty
}
}
}
public extension Api {
enum SecurePasswordKdfAlgo: TypeConstructorDescription {
case securePasswordKdfAlgoPBKDF2HMACSHA512iter100000(salt: Buffer)

View File

@ -670,6 +670,102 @@ public extension Api {
}
}
public extension Api {
enum StarsSubscription: TypeConstructorDescription {
case starsSubscription(flags: Int32, id: String, peer: Api.Peer, untilDate: Int32, pricing: Api.StarsSubscriptionPricing)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsSubscription(let flags, let id, let peer, let untilDate, let pricing):
if boxed {
buffer.appendInt32(-797707802)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeInt32(untilDate, buffer: buffer, boxed: false)
pricing.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsSubscription(let flags, let id, let peer, let untilDate, let pricing):
return ("starsSubscription", [("flags", flags as Any), ("id", id as Any), ("peer", peer as Any), ("untilDate", untilDate as Any), ("pricing", pricing as Any)])
}
}
public static func parse_starsSubscription(_ reader: BufferReader) -> StarsSubscription? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Api.Peer?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.Peer
}
var _4: Int32?
_4 = reader.readInt32()
var _5: Api.StarsSubscriptionPricing?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.StarsSubscription.starsSubscription(flags: _1!, id: _2!, peer: _3!, untilDate: _4!, pricing: _5!)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsSubscriptionPricing: TypeConstructorDescription {
case starsSubscriptionPricing(period: Int32, amount: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsSubscriptionPricing(let period, let amount):
if boxed {
buffer.appendInt32(88173912)
}
serializeInt32(period, buffer: buffer, boxed: false)
serializeInt64(amount, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsSubscriptionPricing(let period, let amount):
return ("starsSubscriptionPricing", [("period", period as Any), ("amount", amount as Any)])
}
}
public static func parse_starsSubscriptionPricing(_ reader: BufferReader) -> StarsSubscriptionPricing? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.StarsSubscriptionPricing.starsSubscriptionPricing(period: _1!, amount: _2!)
}
else {
return nil
}
}
}
}
public extension Api {
enum StarsTopupOption: TypeConstructorDescription {
case starsTopupOption(flags: Int32, stars: Int64, storeProduct: String?, currency: String, amount: Int64)
@ -724,13 +820,13 @@ public extension Api {
}
public extension Api {
enum StarsTransaction: TypeConstructorDescription {
case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?, transactionDate: Int32?, transactionUrl: String?, botPayload: Buffer?, msgId: Int32?, extendedMedia: [Api.MessageMedia]?)
case starsTransaction(flags: Int32, id: String, stars: Int64, date: Int32, peer: Api.StarsTransactionPeer, title: String?, description: String?, photo: Api.WebDocument?, transactionDate: Int32?, transactionUrl: String?, botPayload: Buffer?, msgId: Int32?, extendedMedia: [Api.MessageMedia]?, subscriptionPeriod: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia):
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod):
if boxed {
buffer.appendInt32(766853519)
buffer.appendInt32(1127934763)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(id, buffer: buffer, boxed: false)
@ -749,14 +845,15 @@ public extension Api {
for item in extendedMedia! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 12) != 0 {serializeInt32(subscriptionPeriod!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia):
return ("starsTransaction", [("flags", flags as Any), ("id", id as Any), ("stars", stars as Any), ("date", date as Any), ("peer", peer as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("transactionDate", transactionDate as Any), ("transactionUrl", transactionUrl as Any), ("botPayload", botPayload as Any), ("msgId", msgId as Any), ("extendedMedia", extendedMedia as Any)])
case .starsTransaction(let flags, let id, let stars, let date, let peer, let title, let description, let photo, let transactionDate, let transactionUrl, let botPayload, let msgId, let extendedMedia, let subscriptionPeriod):
return ("starsTransaction", [("flags", flags as Any), ("id", id as Any), ("stars", stars as Any), ("date", date as Any), ("peer", peer as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("transactionDate", transactionDate as Any), ("transactionUrl", transactionUrl as Any), ("botPayload", botPayload as Any), ("msgId", msgId as Any), ("extendedMedia", extendedMedia as Any), ("subscriptionPeriod", subscriptionPeriod as Any)])
}
}
@ -793,6 +890,8 @@ public extension Api {
if Int(_1!) & Int(1 << 9) != 0 {if let _ = reader.readInt32() {
_13 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageMedia.self)
} }
var _14: Int32?
if Int(_1!) & Int(1 << 12) != 0 {_14 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -806,8 +905,9 @@ public extension Api {
let _c11 = (Int(_1!) & Int(1 << 7) == 0) || _11 != nil
let _c12 = (Int(_1!) & Int(1 << 8) == 0) || _12 != nil
let _c13 = (Int(_1!) & Int(1 << 9) == 0) || _13 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 {
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8, transactionDate: _9, transactionUrl: _10, botPayload: _11, msgId: _12, extendedMedia: _13)
let _c14 = (Int(_1!) & Int(1 << 12) == 0) || _14 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 {
return Api.StarsTransaction.starsTransaction(flags: _1!, id: _2!, stars: _3!, date: _4!, peer: _5!, title: _6, description: _7, photo: _8, transactionDate: _9, transactionUrl: _10, botPayload: _11, msgId: _12, extendedMedia: _13, subscriptionPeriod: _14)
}
else {
return nil

View File

@ -1246,21 +1246,28 @@ public extension Api.payments {
}
public extension Api.payments {
enum StarsStatus: TypeConstructorDescription {
case starsStatus(flags: Int32, balance: Int64, history: [Api.StarsTransaction], nextOffset: String?, chats: [Api.Chat], users: [Api.User])
case starsStatus(flags: Int32, balance: Int64, subscriptions: [Api.StarsSubscription]?, subscriptionsNextOffset: String?, subscriptionsMissingBalance: Int64?, history: [Api.StarsTransaction]?, nextOffset: String?, chats: [Api.Chat], users: [Api.User])
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .starsStatus(let flags, let balance, let history, let nextOffset, let chats, let users):
case .starsStatus(let flags, let balance, let subscriptions, let subscriptionsNextOffset, let subscriptionsMissingBalance, let history, let nextOffset, let chats, let users):
if boxed {
buffer.appendInt32(-1930105248)
buffer.appendInt32(-1141231252)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(balance, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(history.count))
for item in history {
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(subscriptions!.count))
for item in subscriptions! {
item.serialize(buffer, true)
}
}}
if Int(flags) & Int(1 << 2) != 0 {serializeString(subscriptionsNextOffset!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeInt64(subscriptionsMissingBalance!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(history!.count))
for item in history! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(chats.count))
@ -1278,8 +1285,8 @@ public extension Api.payments {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .starsStatus(let flags, let balance, let history, let nextOffset, let chats, let users):
return ("starsStatus", [("flags", flags as Any), ("balance", balance as Any), ("history", history as Any), ("nextOffset", nextOffset as Any), ("chats", chats as Any), ("users", users as Any)])
case .starsStatus(let flags, let balance, let subscriptions, let subscriptionsNextOffset, let subscriptionsMissingBalance, let history, let nextOffset, let chats, let users):
return ("starsStatus", [("flags", flags as Any), ("balance", balance as Any), ("subscriptions", subscriptions as Any), ("subscriptionsNextOffset", subscriptionsNextOffset as Any), ("subscriptionsMissingBalance", subscriptionsMissingBalance as Any), ("history", history as Any), ("nextOffset", nextOffset as Any), ("chats", chats as Any), ("users", users as Any)])
}
}
@ -1288,28 +1295,39 @@ public extension Api.payments {
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: [Api.StarsTransaction]?
if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsTransaction.self)
}
var _3: [Api.StarsSubscription]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsSubscription.self)
} }
var _4: String?
if Int(_1!) & Int(1 << 0) != 0 {_4 = parseString(reader) }
var _5: [Api.Chat]?
if Int(_1!) & Int(1 << 2) != 0 {_4 = parseString(reader) }
var _5: Int64?
if Int(_1!) & Int(1 << 4) != 0 {_5 = reader.readInt64() }
var _6: [Api.StarsTransaction]?
if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarsTransaction.self)
} }
var _7: String?
if Int(_1!) & Int(1 << 0) != 0 {_7 = parseString(reader) }
var _8: [Api.Chat]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
}
var _6: [Api.User]?
var _9: [Api.User]?
if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
_9 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.payments.StarsStatus.starsStatus(flags: _1!, balance: _2!, history: _3!, nextOffset: _4, chats: _5!, users: _6!)
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 4) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 3) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 0) == 0) || _7 != nil
let _c8 = _8 != nil
let _c9 = _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.payments.StarsStatus.starsStatus(flags: _1!, balance: _2!, subscriptions: _3, subscriptionsNextOffset: _4, subscriptionsMissingBalance: _5, history: _6, nextOffset: _7, chats: _8!, users: _9!)
}
else {
return nil

View File

@ -5439,15 +5439,16 @@ public extension Api.functions.messages {
}
}
public extension Api.functions.messages {
static func exportChatInvite(flags: Int32, peer: Api.InputPeer, expireDate: Int32?, usageLimit: Int32?, title: String?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) {
static func exportChatInvite(flags: Int32, peer: Api.InputPeer, expireDate: Int32?, usageLimit: Int32?, title: String?, subscriptionPricing: Api.StarsSubscriptionPricing?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.ExportedChatInvite>) {
let buffer = Buffer()
buffer.appendInt32(-1607670315)
buffer.appendInt32(-1537876336)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(expireDate!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(usageLimit!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 4) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("expireDate", String(describing: expireDate)), ("usageLimit", String(describing: usageLimit)), ("title", String(describing: title))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in
if Int(flags) & Int(1 << 5) != 0 {subscriptionPricing!.serialize(buffer, true)}
return (FunctionDescription(name: "messages.exportChatInvite", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("expireDate", String(describing: expireDate)), ("usageLimit", String(describing: usageLimit)), ("title", String(describing: title)), ("subscriptionPricing", String(describing: subscriptionPricing))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.ExportedChatInvite? in
let reader = BufferReader(buffer)
var result: Api.ExportedChatInvite?
if let signature = reader.readInt32() {
@ -7933,6 +7934,24 @@ public extension Api.functions.messages {
})
}
}
public extension Api.functions.messages {
static func sendPaidReaction(peer: Api.InputPeer, msgId: Int32, count: Int32, randomId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(508941107)
peer.serialize(buffer, true)
serializeInt32(msgId, buffer: buffer, boxed: false)
serializeInt32(count, buffer: buffer, boxed: false)
serializeInt64(randomId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "messages.sendPaidReaction", parameters: [("peer", String(describing: peer)), ("msgId", String(describing: msgId)), ("count", String(describing: count)), ("randomId", String(describing: randomId))]), 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 extension Api.functions.messages {
static func sendQuickReplyMessages(peer: Api.InputPeer, shortcutId: Int32, id: [Int32], randomId: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
@ -8132,14 +8151,15 @@ public extension Api.functions.messages {
}
}
public extension Api.functions.messages {
static func setChatAvailableReactions(flags: Int32, peer: Api.InputPeer, availableReactions: Api.ChatReactions, reactionsLimit: Int32?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
static func setChatAvailableReactions(flags: Int32, peer: Api.InputPeer, availableReactions: Api.ChatReactions, reactionsLimit: Int32?, paidEnabled: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
let buffer = Buffer()
buffer.appendInt32(1511328724)
buffer.appendInt32(-2041895551)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
availableReactions.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(reactionsLimit!, buffer: buffer, boxed: false)}
return (FunctionDescription(name: "messages.setChatAvailableReactions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("availableReactions", String(describing: availableReactions)), ("reactionsLimit", String(describing: reactionsLimit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
if Int(flags) & Int(1 << 1) != 0 {paidEnabled!.serialize(buffer, true)}
return (FunctionDescription(name: "messages.setChatAvailableReactions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("availableReactions", String(describing: availableReactions)), ("reactionsLimit", String(describing: reactionsLimit)), ("paidEnabled", String(describing: paidEnabled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in
let reader = BufferReader(buffer)
var result: Api.Updates?
if let signature = reader.readInt32() {
@ -8735,6 +8755,24 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func changeStarsSubscription(flags: Int32, peer: Api.InputPeer, subscriptionId: String, canceled: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(-948500360)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeString(subscriptionId, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {canceled!.serialize(buffer, true)}
return (FunctionDescription(name: "payments.changeStarsSubscription", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("subscriptionId", String(describing: subscriptionId)), ("canceled", String(describing: canceled))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool
}
return result
})
}
}
public extension Api.functions.payments {
static func checkGiftCode(slug: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.CheckedGiftCode>) {
let buffer = Buffer()
@ -8780,6 +8818,22 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func fulfillStarsSubscription(peer: Api.InputPeer, subscriptionId: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
let buffer = Buffer()
buffer.appendInt32(-866391117)
peer.serialize(buffer, true)
serializeString(subscriptionId, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.fulfillStarsSubscription", parameters: [("peer", String(describing: peer)), ("subscriptionId", String(describing: subscriptionId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
let reader = BufferReader(buffer)
var result: Api.Bool?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.Bool
}
return result
})
}
}
public extension Api.functions.payments {
static func getBankCardData(number: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.BankCardData>) {
let buffer = Buffer()
@ -8954,6 +9008,23 @@ public extension Api.functions.payments {
})
}
}
public extension Api.functions.payments {
static func getStarsSubscriptions(flags: Int32, peer: Api.InputPeer, offset: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
let buffer = Buffer()
buffer.appendInt32(52761285)
serializeInt32(flags, buffer: buffer, boxed: false)
peer.serialize(buffer, true)
serializeString(offset, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.getStarsSubscriptions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("offset", String(describing: offset))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in
let reader = BufferReader(buffer)
var result: Api.payments.StarsStatus?
if let signature = reader.readInt32() {
result = Api.parse(reader, signature: signature) as? Api.payments.StarsStatus
}
return result
})
}
}
public extension Api.functions.payments {
static func getStarsTopupOptions() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.StarsTopupOption]>) {
let buffer = Buffer()
@ -8970,14 +9041,15 @@ public extension Api.functions.payments {
}
}
public extension Api.functions.payments {
static func getStarsTransactions(flags: Int32, peer: Api.InputPeer, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
static func getStarsTransactions(flags: Int32, subscriptionId: String?, peer: Api.InputPeer, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarsStatus>) {
let buffer = Buffer()
buffer.appendInt32(-1751937702)
buffer.appendInt32(1775912279)
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 3) != 0 {serializeString(subscriptionId!, buffer: buffer, boxed: false)}
peer.serialize(buffer, true)
serializeString(offset, buffer: buffer, boxed: false)
serializeInt32(limit, buffer: buffer, boxed: false)
return (FunctionDescription(name: "payments.getStarsTransactions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in
return (FunctionDescription(name: "payments.getStarsTransactions", parameters: [("flags", String(describing: flags)), ("subscriptionId", String(describing: subscriptionId)), ("peer", String(describing: peer)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarsStatus? in
let reader = BufferReader(buffer)
var result: Api.payments.StarsStatus?
if let signature = reader.readInt32() {

View File

@ -148,21 +148,23 @@ public extension Api {
}
public extension Api {
enum ChannelParticipant: TypeConstructorDescription {
case channelParticipant(userId: Int64, date: Int32)
case channelParticipant(flags: Int32, userId: Int64, date: Int32, subscriptionUntilDate: Int32?)
case channelParticipantAdmin(flags: Int32, userId: Int64, inviterId: Int64?, promotedBy: Int64, date: Int32, adminRights: Api.ChatAdminRights, rank: String?)
case channelParticipantBanned(flags: Int32, peer: Api.Peer, kickedBy: Int64, date: Int32, bannedRights: Api.ChatBannedRights)
case channelParticipantCreator(flags: Int32, userId: Int64, adminRights: Api.ChatAdminRights, rank: String?)
case channelParticipantLeft(peer: Api.Peer)
case channelParticipantSelf(flags: Int32, userId: Int64, inviterId: Int64, date: Int32)
case channelParticipantSelf(flags: Int32, userId: Int64, inviterId: Int64, date: Int32, subscriptionUntilDate: Int32?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .channelParticipant(let userId, let date):
case .channelParticipant(let flags, let userId, let date, let subscriptionUntilDate):
if boxed {
buffer.appendInt32(-1072953408)
buffer.appendInt32(-885426663)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(userId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(subscriptionUntilDate!, buffer: buffer, boxed: false)}
break
case .channelParticipantAdmin(let flags, let userId, let inviterId, let promotedBy, let date, let adminRights, let rank):
if boxed {
@ -201,22 +203,23 @@ public extension Api {
}
peer.serialize(buffer, true)
break
case .channelParticipantSelf(let flags, let userId, let inviterId, let date):
case .channelParticipantSelf(let flags, let userId, let inviterId, let date, let subscriptionUntilDate):
if boxed {
buffer.appendInt32(900251559)
buffer.appendInt32(1331723247)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt64(userId, buffer: buffer, boxed: false)
serializeInt64(inviterId, buffer: buffer, boxed: false)
serializeInt32(date, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(subscriptionUntilDate!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .channelParticipant(let userId, let date):
return ("channelParticipant", [("userId", userId as Any), ("date", date as Any)])
case .channelParticipant(let flags, let userId, let date, let subscriptionUntilDate):
return ("channelParticipant", [("flags", flags as Any), ("userId", userId as Any), ("date", date as Any), ("subscriptionUntilDate", subscriptionUntilDate as Any)])
case .channelParticipantAdmin(let flags, let userId, let inviterId, let promotedBy, let date, let adminRights, let rank):
return ("channelParticipantAdmin", [("flags", flags as Any), ("userId", userId as Any), ("inviterId", inviterId as Any), ("promotedBy", promotedBy as Any), ("date", date as Any), ("adminRights", adminRights as Any), ("rank", rank as Any)])
case .channelParticipantBanned(let flags, let peer, let kickedBy, let date, let bannedRights):
@ -225,20 +228,26 @@ public extension Api {
return ("channelParticipantCreator", [("flags", flags as Any), ("userId", userId as Any), ("adminRights", adminRights as Any), ("rank", rank as Any)])
case .channelParticipantLeft(let peer):
return ("channelParticipantLeft", [("peer", peer as Any)])
case .channelParticipantSelf(let flags, let userId, let inviterId, let date):
return ("channelParticipantSelf", [("flags", flags as Any), ("userId", userId as Any), ("inviterId", inviterId as Any), ("date", date as Any)])
case .channelParticipantSelf(let flags, let userId, let inviterId, let date, let subscriptionUntilDate):
return ("channelParticipantSelf", [("flags", flags as Any), ("userId", userId as Any), ("inviterId", inviterId as Any), ("date", date as Any), ("subscriptionUntilDate", subscriptionUntilDate as Any)])
}
}
public static func parse_channelParticipant(_ reader: BufferReader) -> ChannelParticipant? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int32?
_2 = reader.readInt32()
var _1: Int32?
_1 = reader.readInt32()
var _2: Int64?
_2 = reader.readInt64()
var _3: Int32?
_3 = reader.readInt32()
var _4: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_4 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.ChannelParticipant.channelParticipant(userId: _1!, date: _2!)
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.ChannelParticipant.channelParticipant(flags: _1!, userId: _2!, date: _3!, subscriptionUntilDate: _4)
}
else {
return nil
@ -346,12 +355,15 @@ public extension Api {
_3 = reader.readInt64()
var _4: Int32?
_4 = reader.readInt32()
var _5: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_5 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.ChannelParticipant.channelParticipantSelf(flags: _1!, userId: _2!, inviterId: _3!, date: _4!)
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.ChannelParticipant.channelParticipantSelf(flags: _1!, userId: _2!, inviterId: _3!, date: _4!, subscriptionUntilDate: _5)
}
else {
return nil
@ -522,7 +534,7 @@ public extension Api {
}
public extension Api {
indirect enum Chat: TypeConstructorDescription {
case channel(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, title: String, username: String?, photo: Api.ChatPhoto, date: Int32, restrictionReason: [Api.RestrictionReason]?, adminRights: Api.ChatAdminRights?, bannedRights: Api.ChatBannedRights?, defaultBannedRights: Api.ChatBannedRights?, participantsCount: Int32?, usernames: [Api.Username]?, storiesMaxId: Int32?, color: Api.PeerColor?, profileColor: Api.PeerColor?, emojiStatus: Api.EmojiStatus?, level: Int32?)
case channel(flags: Int32, flags2: Int32, id: Int64, accessHash: Int64?, title: String, username: String?, photo: Api.ChatPhoto, date: Int32, restrictionReason: [Api.RestrictionReason]?, adminRights: Api.ChatAdminRights?, bannedRights: Api.ChatBannedRights?, defaultBannedRights: Api.ChatBannedRights?, participantsCount: Int32?, usernames: [Api.Username]?, storiesMaxId: Int32?, color: Api.PeerColor?, profileColor: Api.PeerColor?, emojiStatus: Api.EmojiStatus?, level: Int32?, subscriptionUntilDate: Int32?)
case channelForbidden(flags: Int32, id: Int64, accessHash: Int64, title: String, untilDate: Int32?)
case chat(flags: Int32, id: Int64, title: String, photo: Api.ChatPhoto, participantsCount: Int32, date: Int32, version: Int32, migratedTo: Api.InputChannel?, adminRights: Api.ChatAdminRights?, defaultBannedRights: Api.ChatBannedRights?)
case chatEmpty(id: Int64)
@ -530,9 +542,9 @@ public extension Api {
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .channel(let flags, let flags2, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount, let usernames, let storiesMaxId, let color, let profileColor, let emojiStatus, let level):
case .channel(let flags, let flags2, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount, let usernames, let storiesMaxId, let color, let profileColor, let emojiStatus, let level, let subscriptionUntilDate):
if boxed {
buffer.appendInt32(179174543)
buffer.appendInt32(-29067075)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeInt32(flags2, buffer: buffer, boxed: false)
@ -561,6 +573,7 @@ public extension Api {
if Int(flags2) & Int(1 << 8) != 0 {profileColor!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 9) != 0 {emojiStatus!.serialize(buffer, true)}
if Int(flags2) & Int(1 << 10) != 0 {serializeInt32(level!, buffer: buffer, boxed: false)}
if Int(flags2) & Int(1 << 11) != 0 {serializeInt32(subscriptionUntilDate!, buffer: buffer, boxed: false)}
break
case .channelForbidden(let flags, let id, let accessHash, let title, let untilDate):
if boxed {
@ -605,8 +618,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .channel(let flags, let flags2, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount, let usernames, let storiesMaxId, let color, let profileColor, let emojiStatus, let level):
return ("channel", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("title", title as Any), ("username", username as Any), ("photo", photo as Any), ("date", date as Any), ("restrictionReason", restrictionReason as Any), ("adminRights", adminRights as Any), ("bannedRights", bannedRights as Any), ("defaultBannedRights", defaultBannedRights as Any), ("participantsCount", participantsCount as Any), ("usernames", usernames as Any), ("storiesMaxId", storiesMaxId as Any), ("color", color as Any), ("profileColor", profileColor as Any), ("emojiStatus", emojiStatus as Any), ("level", level as Any)])
case .channel(let flags, let flags2, let id, let accessHash, let title, let username, let photo, let date, let restrictionReason, let adminRights, let bannedRights, let defaultBannedRights, let participantsCount, let usernames, let storiesMaxId, let color, let profileColor, let emojiStatus, let level, let subscriptionUntilDate):
return ("channel", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("title", title as Any), ("username", username as Any), ("photo", photo as Any), ("date", date as Any), ("restrictionReason", restrictionReason as Any), ("adminRights", adminRights as Any), ("bannedRights", bannedRights as Any), ("defaultBannedRights", defaultBannedRights as Any), ("participantsCount", participantsCount as Any), ("usernames", usernames as Any), ("storiesMaxId", storiesMaxId as Any), ("color", color as Any), ("profileColor", profileColor as Any), ("emojiStatus", emojiStatus as Any), ("level", level as Any), ("subscriptionUntilDate", subscriptionUntilDate as Any)])
case .channelForbidden(let flags, let id, let accessHash, let title, let untilDate):
return ("channelForbidden", [("flags", flags as Any), ("id", id as Any), ("accessHash", accessHash as Any), ("title", title as Any), ("untilDate", untilDate as Any)])
case .chat(let flags, let id, let title, let photo, let participantsCount, let date, let version, let migratedTo, let adminRights, let defaultBannedRights):
@ -675,6 +688,8 @@ public extension Api {
} }
var _19: Int32?
if Int(_2!) & Int(1 << 10) != 0 {_19 = reader.readInt32() }
var _20: Int32?
if Int(_2!) & Int(1 << 11) != 0 {_20 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -694,8 +709,9 @@ public extension Api {
let _c17 = (Int(_2!) & Int(1 << 8) == 0) || _17 != nil
let _c18 = (Int(_2!) & Int(1 << 9) == 0) || _18 != nil
let _c19 = (Int(_2!) & Int(1 << 10) == 0) || _19 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 {
return Api.Chat.channel(flags: _1!, flags2: _2!, id: _3!, accessHash: _4, title: _5!, username: _6, photo: _7!, date: _8!, restrictionReason: _9, adminRights: _10, bannedRights: _11, defaultBannedRights: _12, participantsCount: _13, usernames: _14, storiesMaxId: _15, color: _16, profileColor: _17, emojiStatus: _18, level: _19)
let _c20 = (Int(_2!) & Int(1 << 11) == 0) || _20 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 {
return Api.Chat.channel(flags: _1!, flags2: _2!, id: _3!, accessHash: _4, title: _5!, username: _6, photo: _7!, date: _8!, restrictionReason: _9, adminRights: _10, bannedRights: _11, defaultBannedRights: _12, participantsCount: _13, usernames: _14, storiesMaxId: _15, color: _16, profileColor: _17, emojiStatus: _18, level: _19, subscriptionUntilDate: _20)
}
else {
return nil
@ -1280,15 +1296,15 @@ public extension Api {
}
public extension Api {
indirect enum ChatInvite: TypeConstructorDescription {
case chatInvite(flags: Int32, title: String, about: String?, photo: Api.Photo, participantsCount: Int32, participants: [Api.User]?, color: Int32)
case chatInvite(flags: Int32, title: String, about: String?, photo: Api.Photo, participantsCount: Int32, participants: [Api.User]?, color: Int32, subscriptionPricing: Api.StarsSubscriptionPricing?, subscriptionFormId: Int64?)
case chatInviteAlready(chat: Api.Chat)
case chatInvitePeek(chat: Api.Chat, expires: Int32)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .chatInvite(let flags, let title, let about, let photo, let participantsCount, let participants, let color):
case .chatInvite(let flags, let title, let about, let photo, let participantsCount, let participants, let color, let subscriptionPricing, let subscriptionFormId):
if boxed {
buffer.appendInt32(-840897472)
buffer.appendInt32(-26920803)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(title, buffer: buffer, boxed: false)
@ -1301,6 +1317,8 @@ public extension Api {
item.serialize(buffer, true)
}}
serializeInt32(color, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 10) != 0 {subscriptionPricing!.serialize(buffer, true)}
if Int(flags) & Int(1 << 12) != 0 {serializeInt64(subscriptionFormId!, buffer: buffer, boxed: false)}
break
case .chatInviteAlready(let chat):
if boxed {
@ -1320,8 +1338,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .chatInvite(let flags, let title, let about, let photo, let participantsCount, let participants, let color):
return ("chatInvite", [("flags", flags as Any), ("title", title as Any), ("about", about as Any), ("photo", photo as Any), ("participantsCount", participantsCount as Any), ("participants", participants as Any), ("color", color as Any)])
case .chatInvite(let flags, let title, let about, let photo, let participantsCount, let participants, let color, let subscriptionPricing, let subscriptionFormId):
return ("chatInvite", [("flags", flags as Any), ("title", title as Any), ("about", about as Any), ("photo", photo as Any), ("participantsCount", participantsCount as Any), ("participants", participants as Any), ("color", color as Any), ("subscriptionPricing", subscriptionPricing as Any), ("subscriptionFormId", subscriptionFormId as Any)])
case .chatInviteAlready(let chat):
return ("chatInviteAlready", [("chat", chat as Any)])
case .chatInvitePeek(let chat, let expires):
@ -1348,6 +1366,12 @@ public extension Api {
} }
var _7: Int32?
_7 = reader.readInt32()
var _8: Api.StarsSubscriptionPricing?
if Int(_1!) & Int(1 << 10) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
} }
var _9: Int64?
if Int(_1!) & Int(1 << 12) != 0 {_9 = reader.readInt64() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 5) == 0) || _3 != nil
@ -1355,8 +1379,10 @@ public extension Api {
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 4) == 0) || _6 != nil
let _c7 = _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.ChatInvite.chatInvite(flags: _1!, title: _2!, about: _3, photo: _4!, participantsCount: _5!, participants: _6, color: _7!)
let _c8 = (Int(_1!) & Int(1 << 10) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 12) == 0) || _9 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
return Api.ChatInvite.chatInvite(flags: _1!, title: _2!, about: _3, photo: _4!, participantsCount: _5!, participants: _6, color: _7!, subscriptionPricing: _8, subscriptionFormId: _9)
}
else {
return nil

View File

@ -1012,14 +1012,14 @@ public extension Api {
}
public extension Api {
enum ExportedChatInvite: TypeConstructorDescription {
case chatInviteExported(flags: Int32, link: String, adminId: Int64, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?, requested: Int32?, title: String?)
case chatInviteExported(flags: Int32, link: String, adminId: Int64, date: Int32, startDate: Int32?, expireDate: Int32?, usageLimit: Int32?, usage: Int32?, requested: Int32?, title: String?, subscriptionPricing: Api.StarsSubscriptionPricing?)
case chatInvitePublicJoinRequests
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title):
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title, let subscriptionPricing):
if boxed {
buffer.appendInt32(179611673)
buffer.appendInt32(-1812799720)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(link, buffer: buffer, boxed: false)
@ -1031,6 +1031,7 @@ public extension Api {
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(usage!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 7) != 0 {serializeInt32(requested!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 8) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 9) != 0 {subscriptionPricing!.serialize(buffer, true)}
break
case .chatInvitePublicJoinRequests:
if boxed {
@ -1043,8 +1044,8 @@ public extension Api {
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title):
return ("chatInviteExported", [("flags", flags as Any), ("link", link as Any), ("adminId", adminId as Any), ("date", date as Any), ("startDate", startDate as Any), ("expireDate", expireDate as Any), ("usageLimit", usageLimit as Any), ("usage", usage as Any), ("requested", requested as Any), ("title", title as Any)])
case .chatInviteExported(let flags, let link, let adminId, let date, let startDate, let expireDate, let usageLimit, let usage, let requested, let title, let subscriptionPricing):
return ("chatInviteExported", [("flags", flags as Any), ("link", link as Any), ("adminId", adminId as Any), ("date", date as Any), ("startDate", startDate as Any), ("expireDate", expireDate as Any), ("usageLimit", usageLimit as Any), ("usage", usage as Any), ("requested", requested as Any), ("title", title as Any), ("subscriptionPricing", subscriptionPricing as Any)])
case .chatInvitePublicJoinRequests:
return ("chatInvitePublicJoinRequests", [])
}
@ -1071,6 +1072,10 @@ public extension Api {
if Int(_1!) & Int(1 << 7) != 0 {_9 = reader.readInt32() }
var _10: String?
if Int(_1!) & Int(1 << 8) != 0 {_10 = parseString(reader) }
var _11: Api.StarsSubscriptionPricing?
if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() {
_11 = Api.parse(reader, signature: signature) as? Api.StarsSubscriptionPricing
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -1081,8 +1086,9 @@ public extension Api {
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
let _c9 = (Int(_1!) & Int(1 << 7) == 0) || _9 != nil
let _c10 = (Int(_1!) & Int(1 << 8) == 0) || _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8, requested: _9, title: _10)
let _c11 = (Int(_1!) & Int(1 << 9) == 0) || _11 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 {
return Api.ExportedChatInvite.chatInviteExported(flags: _1!, link: _2!, adminId: _3!, date: _4!, startDate: _5, expireDate: _6, usageLimit: _7, usage: _8, requested: _9, title: _10, subscriptionPricing: _11)
}
else {
return nil

View File

@ -478,7 +478,7 @@ struct AccountMutableState {
for chat in chats {
switch chat {
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _):
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _):
if let participantsCount = participantsCount {
self.addOperation(.UpdateCachedPeerData(chat.peerId, { current in
var previous: CachedChannelData

View File

@ -109,6 +109,7 @@ private var declaredEncodables: Void = {
declareEncodable(ReplyThreadMessageAttribute.self, f: { ReplyThreadMessageAttribute(decoder: $0) })
declareEncodable(ReactionsMessageAttribute.self, f: { ReactionsMessageAttribute(decoder: $0) })
declareEncodable(PendingReactionsMessageAttribute.self, f: { PendingReactionsMessageAttribute(decoder: $0) })
declareEncodable(PendingStarsReactionsMessageAttribute.self, f: { PendingStarsReactionsMessageAttribute(decoder: $0) })
declareEncodable(CloudDocumentMediaResource.self, f: { CloudDocumentMediaResource(decoder: $0) })
declareEncodable(TelegramMediaWebpage.self, f: { TelegramMediaWebpage(decoder: $0) })
declareEncodable(ViewCountMessageAttribute.self, f: { ViewCountMessageAttribute(decoder: $0) })
@ -188,6 +189,7 @@ private var declaredEncodables: Void = {
declareEncodable(WasScheduledMessageAttribute.self, f: { WasScheduledMessageAttribute(decoder: $0) })
declareEncodable(OutgoingScheduleInfoMessageAttribute.self, f: { OutgoingScheduleInfoMessageAttribute(decoder: $0) })
declareEncodable(UpdateMessageReactionsAction.self, f: { UpdateMessageReactionsAction(decoder: $0) })
declareEncodable(SendStarsReactionsAction.self, f: { SendStarsReactionsAction(decoder: $0) })
declareEncodable(RestrictedContentMessageAttribute.self, f: { RestrictedContentMessageAttribute(decoder: $0) })
declareEncodable(SendScheduledMessageImmediatelyAction.self, f: { SendScheduledMessageImmediatelyAction(decoder: $0) })
declareEncodable(EmbeddedMediaStickersMessageAttribute.self, f: { EmbeddedMediaStickersMessageAttribute(decoder: $0) })

View File

@ -61,7 +61,7 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), title: "", photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
case let .chatForbidden(id, title):
return TelegramGroup(id: PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id)), title: title, photo: [], participantCount: 0, role: .member, membership: .Removed, flags: [], defaultBannedRights: nil, migrationReference: nil, creationDate: 0, version: 0)
case let .channel(flags, flags2, id, accessHash, title, username, photo, date, restrictionReason, adminRights, bannedRights, defaultBannedRights, _, usernames, _, color, profileColor, emojiStatus, boostLevel):
case let .channel(flags, flags2, id, accessHash, title, username, photo, date, restrictionReason, adminRights, bannedRights, defaultBannedRights, _, usernames, _, color, profileColor, emojiStatus, boostLevel, _):
let isMin = (flags & (1 << 12)) != 0
let participationStatus: TelegramChannelParticipationStatus
@ -190,7 +190,7 @@ func mergeGroupOrChannel(lhs: Peer?, rhs: Api.Chat) -> Peer? {
switch rhs {
case .chat, .chatEmpty, .chatForbidden, .channelForbidden:
return parseTelegramGroupOrChannel(chat: rhs)
case let .channel(flags, flags2, _, accessHash, title, username, photo, _, _, _, _, defaultBannedRights, _, usernames, _, color, profileColor, emojiStatus, boostLevel):
case let .channel(flags, flags2, _, accessHash, title, username, photo, _, _, _, _, defaultBannedRights, _, usernames, _, color, profileColor, emojiStatus, boostLevel, _):
let isMin = (flags & (1 << 12)) != 0
if accessHash != nil && !isMin {
return parseTelegramGroupOrChannel(chat: rhs)

View File

@ -197,7 +197,7 @@ public final class CachedChannelParticipants: PostboxCoding, Equatable {
extension ChannelParticipant {
init(apiParticipant: Api.ChannelParticipant) {
switch apiParticipant {
case let .channelParticipant(userId, date):
case let .channelParticipant(_, userId, date, _):
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), invitedAt: date, adminInfo: nil, banInfo: nil, rank: nil)
case let .channelParticipantCreator(_, userId, adminRights, rank):
self = .creator(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(apiAdminRights: adminRights) ?? TelegramChatAdminRights(rights: []), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), canBeEditedByAccountPeer: true), rank: rank)
@ -207,7 +207,7 @@ extension ChannelParticipant {
self = .member(id: userId.peerId, invitedAt: date, adminInfo: nil, banInfo: banInfo, rank: nil)
case let .channelParticipantAdmin(flags, userId, _, promotedBy, date, adminRights, rank: rank):
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), invitedAt: date, adminInfo: ChannelParticipantAdminInfo(rights: TelegramChatAdminRights(apiAdminRights: adminRights) ?? TelegramChatAdminRights(rights: []), promotedBy: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(promotedBy)), canBeEditedByAccountPeer: (flags & (1 << 0)) != 0), banInfo: nil, rank: rank)
case let .channelParticipantSelf(_, userId, _, date):
case let .channelParticipantSelf(_, userId, _, date, _):
self = .member(id: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(userId)), invitedAt: date, adminInfo: nil, banInfo: nil, rank: nil)
case let .channelParticipantLeft(userId):
self = .member(id: userId.peerId, invitedAt: 0, adminInfo: nil, banInfo: nil, rank: nil)

View File

@ -6,7 +6,7 @@ import TelegramApi
extension ExportedInvitation {
init(apiExportedInvite: Api.ExportedChatInvite) {
switch apiExportedInvite {
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested, title):
case let .chatInviteExported(flags, link, adminId, date, startDate, expireDate, usageLimit, usage, requested, title, _):
self = .link(link: link, title: title, isPermanent: (flags & (1 << 5)) != 0, requestApproval: (flags & (1 << 6)) != 0, isRevoked: (flags & (1 << 0)) != 0, adminId: PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(adminId)), date: date, startDate: startDate, expireDate: expireDate, usageLimit: usageLimit, count: usage, requestedCount: requested)
case .chatInvitePublicJoinRequests:
self = .publicJoinRequest

View File

@ -5,7 +5,10 @@ import TelegramApi
extension ReactionsMessageAttribute {
func withUpdatedResults(_ reactions: Api.MessageReactions) -> ReactionsMessageAttribute {
switch reactions {
case let .messageReactions(flags, results, recentReactions):
case let .messageReactions(flags, results, recentReactions, topReactors):
//TODO:release
let _ = topReactors
let min = (flags & (1 << 0)) != 0
let canViewList = (flags & (1 << 2)) != 0
let isTags = (flags & (1 << 3)) != 0
@ -94,26 +97,7 @@ public func mergedMessageReactionsAndPeers(accountPeerId: EnginePeer.Id, account
}
}
#if DEBUG
var reactions = attribute.reactions
if "".isEmpty {
if let index = reactions.firstIndex(where: {
if case .custom(MessageReaction.starsReactionId) = $0.value {
return true
} else {
return false
}
}) {
let value = reactions[index]
reactions.remove(at: index)
reactions.insert(value, at: 0)
} else {
reactions.insert(MessageReaction(value: .custom(MessageReaction.starsReactionId), count: 1000000, chosenOrder: nil), at: 0)
}
}
#else
let reactions = attribute.reactions
#endif
return (reactions, recentPeers)
}
@ -174,14 +158,18 @@ private func mergeReactions(reactions: [MessageReaction], recentPeers: [Reaction
public func mergedMessageReactions(attributes: [MessageAttribute], isTags: Bool) -> ReactionsMessageAttribute? {
var current: ReactionsMessageAttribute?
var pending: PendingReactionsMessageAttribute?
var pendingStars: PendingStarsReactionsMessageAttribute?
for attribute in attributes {
if let attribute = attribute as? ReactionsMessageAttribute {
current = attribute
} else if let attribute = attribute as? PendingReactionsMessageAttribute {
pending = attribute
} else if let attribute = attribute as? PendingStarsReactionsMessageAttribute {
pendingStars = attribute
}
}
let result: ReactionsMessageAttribute?
if let pending = pending, let accountPeerId = pending.accountPeerId {
var reactions = current?.reactions ?? []
var recentPeers = current?.recentPeers ?? []
@ -191,21 +179,40 @@ public func mergedMessageReactions(attributes: [MessageAttribute], isTags: Bool)
recentPeers = updatedRecentPeers
if !reactions.isEmpty {
return ReactionsMessageAttribute(canViewList: current?.canViewList ?? false, isTags: current?.isTags ?? isTags, reactions: reactions, recentPeers: recentPeers)
result = ReactionsMessageAttribute(canViewList: current?.canViewList ?? false, isTags: current?.isTags ?? isTags, reactions: reactions, recentPeers: recentPeers)
} else {
return nil
result = nil
}
} else if let current = current {
return current
} else if let current {
result = current
} else {
return nil
result = nil
}
if let pendingStars {
if let result {
var reactions = result.reactions
var updatedCount: Int32 = pendingStars.count
if let index = reactions.firstIndex(where: { $0.value == .stars }) {
updatedCount += reactions[index].count
reactions.remove(at: index)
}
reactions.insert(MessageReaction(value: .stars, count: updatedCount, chosenOrder: -1), at: 0)
return ReactionsMessageAttribute(canViewList: current?.canViewList ?? false, isTags: current?.isTags ?? isTags, reactions: reactions, recentPeers: result.recentPeers)
} else {
return ReactionsMessageAttribute(canViewList: current?.canViewList ?? false, isTags: current?.isTags ?? isTags, reactions: [MessageReaction(value: .stars, count: pendingStars.count, chosenOrder: -1)], recentPeers: [])
}
} else {
return result
}
}
extension ReactionsMessageAttribute {
convenience init(apiReactions: Api.MessageReactions) {
switch apiReactions {
case let .messageReactions(flags, results, recentReactions):
case let .messageReactions(flags, results, recentReactions, topReactors):
//TODO:release
let _ = topReactors
let canViewList = (flags & (1 << 2)) != 0
let isTags = (flags & (1 << 3)) != 0
let parsedRecentReactions: [ReactionsMessageAttribute.RecentPeer]

View File

@ -22,6 +22,8 @@ public extension ReactionSettings {
} else {
return ReactionSettings.default.quickReaction
}
case .stars:
return self.quickReaction
}
}
}

View File

@ -87,6 +87,7 @@ final class AccountTaskManager {
tasks.add(managedSynchronizeMarkAllUnseenPersonalMessagesOperations(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start())
tasks.add(managedSynchronizeMarkAllUnseenReactionsOperations(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start())
tasks.add(managedApplyPendingMessageReactionsActions(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start())
tasks.add(managedApplyPendingMessageStarsReactionsActions(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start())
tasks.add(managedSynchronizeEmojiKeywordsOperations(postbox: self.stateManager.postbox, network: self.stateManager.network).start())
tasks.add(managedApplyPendingScheduledMessagesActions(postbox: self.stateManager.postbox, network: self.stateManager.network, stateManager: self.stateManager).start())
tasks.add(managedSynchronizeAvailableReactions(postbox: self.stateManager.postbox, network: self.stateManager.network).start())

View File

@ -142,6 +142,8 @@ public final class AvailableReactions: Equatable, Codable {
try container.encode(value, forKey: .value)
case .custom:
break
case .stars:
break
}
try container.encode(self.title, forKey: .title)
@ -172,7 +174,29 @@ public final class AvailableReactions: Equatable, Codable {
reactions: [Reaction]
) {
self.hash = hash
#if DEBUG
var reactions = reactions
reactions.removeAll(where: { if case .stars = $0.value { return true } else { return false } })
if let item = reactions.first(where: { if case .builtin("🤩") = $0.value { return true } else { return false } }) {
reactions.append(Reaction(
isEnabled: false,
isPremium: false,
value: .stars,
title: "Star",
staticIcon: item.staticIcon,
appearAnimation: item.appearAnimation,
selectAnimation: item.selectAnimation,
activateAnimation: item.activateAnimation,
effectAnimation: item.effectAnimation,
aroundAnimation: item.aroundAnimation,
centerAnimation: item.centerAnimation
))
}
self.reactions = reactions
#else
self.reactions = reactions
#endif
}
public static func ==(lhs: AvailableReactions, rhs: AvailableReactions) -> Bool {
@ -189,7 +213,28 @@ public final class AvailableReactions: Equatable, Codable {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.hash = try container.decodeIfPresent(Int32.self, forKey: .newHash) ?? 0
#if DEBUG
var reactions = try container.decode([Reaction].self, forKey: .reactions)
reactions.removeAll(where: { if case .stars = $0.value { return true } else { return false } })
if let item = reactions.first(where: { if case .builtin("🤩") = $0.value { return true } else { return false } }) {
reactions.append(Reaction(
isEnabled: false,
isPremium: false,
value: .stars,
title: "Star",
staticIcon: item.staticIcon,
appearAnimation: item.appearAnimation,
selectAnimation: item.selectAnimation,
activateAnimation: item.activateAnimation,
effectAnimation: item.effectAnimation,
aroundAnimation: item.aroundAnimation,
centerAnimation: item.centerAnimation
))
}
self.reactions = reactions
#else
self.reactions = try container.decode([Reaction].self, forKey: .reactions)
#endif
}
public func encode(to encoder: Encoder) throws {

View File

@ -656,6 +656,8 @@ func synchronizeSavedMessageTags(postbox: Postbox, network: Network, peerId: Pee
reactionId = UInt64(bitPattern: id)
case let .builtin(string):
reactionId = md5StringHash(string)
case .stars:
reactionId = md5StringHash("star")
}
var titleId: UInt64?

View File

@ -411,6 +411,8 @@ func managedRecentReactions(postbox: Postbox, network: Network) -> Signal<Void,
return 0
case let .custom(fileId):
return fileId.id
case .stars:
return 0
}
}, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getRecentReactions(limit: 100, hash: hash))
@ -428,6 +430,8 @@ func managedRecentReactions(postbox: Postbox, network: Network) -> Signal<Void,
return nil
case let .custom(fileId):
return fileId
case .stars:
return nil
}
})
|> map { files -> [OrderedItemListEntry] in
@ -442,6 +446,8 @@ func managedRecentReactions(postbox: Postbox, network: Network) -> Signal<Void,
continue
}
item = RecentReactionItem(.custom(file))
case .stars:
item = RecentReactionItem(.stars)
}
if let entry = CodableEntry(item) {
items.append(OrderedItemListEntry(id: item.id.rawValue, contents: entry))
@ -462,6 +468,8 @@ func managedTopReactions(postbox: Postbox, network: Network) -> Signal<Void, NoE
return 0
case let .custom(fileId):
return fileId.id
case .stars:
return 0
}
}, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getTopReactions(limit: 32, hash: hash))
@ -479,6 +487,8 @@ func managedTopReactions(postbox: Postbox, network: Network) -> Signal<Void, NoE
return nil
case let .custom(fileId):
return fileId
case .stars:
return nil
}
})
|> map { files -> [OrderedItemListEntry] in
@ -493,6 +503,8 @@ func managedTopReactions(postbox: Postbox, network: Network) -> Signal<Void, NoE
continue
}
item = RecentReactionItem(.custom(file))
case .stars:
item = RecentReactionItem(.stars)
}
if let entry = CodableEntry(item) {
items.append(OrderedItemListEntry(id: item.id.rawValue, contents: entry))
@ -513,6 +525,8 @@ func managedDefaultTagReactions(postbox: Postbox, network: Network) -> Signal<Vo
return 0
case let .custom(fileId):
return fileId.id
case .stars:
return 0
}
}, reverseHashOrder: false, forceFetch: false, fetch: { hash in
return network.request(Api.functions.messages.getDefaultTagReactions(hash: hash))
@ -530,6 +544,8 @@ func managedDefaultTagReactions(postbox: Postbox, network: Network) -> Signal<Vo
return nil
case let .custom(fileId):
return fileId
case .stars:
return nil
}
})
|> map { files -> [OrderedItemListEntry] in
@ -544,6 +560,8 @@ func managedDefaultTagReactions(postbox: Postbox, network: Network) -> Signal<Vo
continue
}
item = RecentReactionItem(.custom(file))
case .stars:
item = RecentReactionItem(.stars)
}
if let entry = CodableEntry(item) {
items.append(OrderedItemListEntry(id: item.id.rawValue, contents: entry))

View File

@ -7,6 +7,7 @@ import MtProtoKit
public enum UpdateMessageReaction {
case builtin(String)
case custom(fileId: Int64, file: TelegramMediaFile?)
case stars
public var reaction: MessageReaction.Reaction {
switch self {
@ -14,6 +15,8 @@ public enum UpdateMessageReaction {
return .builtin(value)
case let .custom(fileId, _):
return .custom(fileId)
case .stars:
return .stars
}
}
}
@ -83,6 +86,8 @@ public func updateMessageReactionsInteractively(account: Account, messageIds: [M
mappedValue = .builtin(value)
case let .custom(fileId):
mappedValue = .custom(fileId: fileId, file: nil)
case .stars:
mappedValue = .stars
}
reactions.append(mappedValue)
}
@ -99,6 +104,8 @@ public func updateMessageReactionsInteractively(account: Account, messageIds: [M
}
case let .builtin(value):
mappedReactions.append(PendingReactionsMessageAttribute.PendingReaction(value: .builtin(value), sendAsPeerId: sendAsPeerId))
case .stars:
mappedReactions.append(PendingReactionsMessageAttribute.PendingReaction(value: .stars, sendAsPeerId: sendAsPeerId))
}
}
@ -132,6 +139,8 @@ public func updateMessageReactionsInteractively(account: Account, messageIds: [M
} else {
continue
}
case .stars:
recentReactionItem = RecentReactionItem(.stars)
}
if let entry = CodableEntry(recentReactionItem) {
@ -163,6 +172,32 @@ public func updateMessageReactionsInteractively(account: Account, messageIds: [M
|> ignoreValues
}
public func sendStarsReactionsInteractively(account: Account, messageId: MessageId, count: Int) -> Signal<Never, NoError> {
return account.postbox.transaction { transaction -> Void in
transaction.setPendingMessageAction(type: .sendStarsReaction, id: messageId, action: SendStarsReactionsAction(randomId: Int64.random(in: Int64.min ... Int64.max)))
transaction.updateMessage(messageId, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags)
}
var mappedCount = Int32(count)
var attributes = currentMessage.attributes
loop: for j in 0 ..< attributes.count {
if let current = attributes[j] as? PendingStarsReactionsMessageAttribute {
mappedCount += current.count
attributes.remove(at: j)
break loop
}
}
attributes.append(PendingStarsReactionsMessageAttribute(accountPeerId: account.peerId, count: mappedCount))
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))
})
}
|> ignoreValues
}
private enum RequestUpdateMessageReactionError {
case generic
}
@ -250,6 +285,76 @@ private func requestUpdateMessageReaction(postbox: Postbox, network: Network, st
}
}
private func requestSendStarsReaction(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId) -> Signal<Never, RequestUpdateMessageReactionError> {
return postbox.transaction { transaction -> (Peer, Int32)? in
guard let peer = transaction.getPeer(messageId.peerId) else {
return nil
}
guard let message = transaction.getMessage(messageId) else {
return nil
}
var count: Int32 = 0
for attribute in message.attributes {
if let attribute = attribute as? PendingStarsReactionsMessageAttribute {
count += attribute.count
break
}
}
return (peer, count)
}
|> castError(RequestUpdateMessageReactionError.self)
|> mapToSignal { peerAndValue in
guard let (peer, count) = peerAndValue else {
return .fail(.generic)
}
guard let inputPeer = apiInputPeer(peer) else {
return .fail(.generic)
}
if messageId.namespace != Namespaces.Message.Cloud {
return .fail(.generic)
}
if count > 0 {
let randomPartId = UInt64(UInt32(bitPattern: Int32.random(in: Int32.min ... Int32.max)))
let timestampPart = UInt64(UInt32(bitPattern: Int32(Date().timeIntervalSince1970)))
let randomId = (timestampPart << 32) | randomPartId
let signal: Signal<Never, RequestUpdateMessageReactionError> = network.request(Api.functions.messages.sendPaidReaction(peer: inputPeer, msgId: messageId.id, count: count, randomId: Int64(bitPattern: randomId)))
|> mapError { _ -> RequestUpdateMessageReactionError in
return .generic
}
|> mapToSignal { result -> Signal<Never, RequestUpdateMessageReactionError> in
return postbox.transaction { transaction -> Void in
transaction.setPendingMessageAction(type: .sendStarsReaction, id: messageId, action: UpdateMessageReactionsAction())
transaction.updateMessage(messageId, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags)
}
let reactions = mergedMessageReactions(attributes: currentMessage.attributes, isTags: currentMessage.areReactionsTags(accountPeerId: stateManager.accountPeerId))
var attributes = currentMessage.attributes
for j in (0 ..< attributes.count).reversed() {
if attributes[j] is PendingStarsReactionsMessageAttribute || attributes[j] is ReactionsMessageAttribute {
attributes.remove(at: j)
}
}
if let reactions {
attributes.append(reactions)
}
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))
})
stateManager.addUpdates(result)
}
|> castError(RequestUpdateMessageReactionError.self)
|> ignoreValues
}
return signal
} else {
return .complete()
}
}
}
private final class ManagedApplyPendingMessageReactionsActionsHelper {
var operationDisposables: [MessageId: Disposable] = [:]
@ -294,7 +399,7 @@ private final class ManagedApplyPendingMessageReactionsActionsHelper {
}
}
private func withTakenAction(postbox: Postbox, type: PendingMessageActionType, id: MessageId, _ f: @escaping (Transaction, PendingMessageActionsEntry?) -> Signal<Never, NoError>) -> Signal<Never, NoError> {
private func withTakenReactionsAction(postbox: Postbox, type: PendingMessageActionType, id: MessageId, _ f: @escaping (Transaction, PendingMessageActionsEntry?) -> Signal<Never, NoError>) -> Signal<Never, NoError> {
return postbox.transaction { transaction -> Signal<Never, NoError> in
var result: PendingMessageActionsEntry?
@ -307,6 +412,19 @@ private func withTakenAction(postbox: Postbox, type: PendingMessageActionType, i
|> switchToLatest
}
private func withTakenStarsAction(postbox: Postbox, type: PendingMessageActionType, id: MessageId, _ f: @escaping (Transaction, PendingMessageActionsEntry?) -> Signal<Never, NoError>) -> Signal<Never, NoError> {
return postbox.transaction { transaction -> Signal<Never, NoError> in
var result: PendingMessageActionsEntry?
if let action = transaction.getPendingMessageAction(type: type, id: id) as? SendStarsReactionsAction {
result = PendingMessageActionsEntry(id: id, action: action)
}
return f(transaction, result)
}
|> switchToLatest
}
func managedApplyPendingMessageReactionsActions(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
return Signal { _ in
let helper = Atomic<ManagedApplyPendingMessageReactionsActionsHelper>(value: ManagedApplyPendingMessageReactionsActionsHelper())
@ -327,7 +445,7 @@ func managedApplyPendingMessageReactionsActions(postbox: Postbox, network: Netwo
}
for (entry, disposable) in beginOperations {
let signal = withTakenAction(postbox: postbox, type: .updateReaction, id: entry.id, { transaction, entry -> Signal<Never, NoError> in
let signal = withTakenReactionsAction(postbox: postbox, type: .updateReaction, id: entry.id, { transaction, entry -> Signal<Never, NoError> in
if let entry = entry {
if let _ = entry.action as? UpdateMessageReactionsAction {
return synchronizeMessageReactions(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, id: entry.id)
@ -360,6 +478,60 @@ func managedApplyPendingMessageReactionsActions(postbox: Postbox, network: Netwo
}
}
func managedApplyPendingMessageStarsReactionsActions(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal<Void, NoError> {
return Signal { _ in
let helper = Atomic<ManagedApplyPendingMessageReactionsActionsHelper>(value: ManagedApplyPendingMessageReactionsActionsHelper())
let actionsKey = PostboxViewKey.pendingMessageActions(type: .sendStarsReaction)
let disposable = postbox.combinedView(keys: [actionsKey]).start(next: { view in
var entries: [PendingMessageActionsEntry] = []
if let v = view.views[actionsKey] as? PendingMessageActionsView {
entries = v.entries
}
let (disposeOperations, beginOperations) = helper.with { helper -> (disposeOperations: [Disposable], beginOperations: [(PendingMessageActionsEntry, MetaDisposable)]) in
return helper.update(entries: entries)
}
for disposable in disposeOperations {
disposable.dispose()
}
for (entry, disposable) in beginOperations {
let signal = withTakenStarsAction(postbox: postbox, type: .sendStarsReaction, id: entry.id, { transaction, entry -> Signal<Never, NoError> in
if let entry = entry {
if let _ = entry.action as? SendStarsReactionsAction {
return synchronizeMessageStarsReactions(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, id: entry.id)
|> delay(5.0, queue: .mainQueue())
} else {
assertionFailure()
}
}
return .complete()
})
|> then(
postbox.transaction { transaction -> Void in
transaction.setPendingMessageAction(type: .sendStarsReaction, id: entry.id, action: nil)
}
|> ignoreValues
)
disposable.set(signal.start())
}
})
return ActionDisposable {
let disposables = helper.with { helper -> [Disposable] in
return helper.reset()
}
for disposable in disposables {
disposable.dispose()
}
disposable.dispose()
}
}
}
private func synchronizeMessageReactions(transaction: Transaction, postbox: Postbox, network: Network, stateManager: AccountStateManager, id: MessageId) -> Signal<Never, NoError> {
return requestUpdateMessageReaction(postbox: postbox, network: network, stateManager: stateManager, messageId: id)
|> `catch` { _ -> Signal<Never, NoError> in
@ -384,6 +556,30 @@ private func synchronizeMessageReactions(transaction: Transaction, postbox: Post
}
}
private func synchronizeMessageStarsReactions(transaction: Transaction, postbox: Postbox, network: Network, stateManager: AccountStateManager, id: MessageId) -> Signal<Never, NoError> {
return requestSendStarsReaction(postbox: postbox, network: network, stateManager: stateManager, messageId: id)
|> `catch` { _ -> Signal<Never, NoError> in
return postbox.transaction { transaction -> Void in
transaction.setPendingMessageAction(type: .sendStarsReaction, id: id, action: nil)
transaction.updateMessage(id, update: { currentMessage in
var storeForwardInfo: StoreMessageForwardInfo?
if let forwardInfo = currentMessage.forwardInfo {
storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags)
}
var attributes = currentMessage.attributes
loop: for j in 0 ..< attributes.count {
if let _ = attributes[j] as? PendingStarsReactionsMessageAttribute {
attributes.remove(at: j)
break loop
}
}
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))
})
}
|> ignoreValues
}
}
public extension EngineMessageReactionListContext.State {
init(message: EngineMessage, readStats: MessageReadStats?, reaction: MessageReaction.Reaction?) {
var totalCount = 0
@ -682,7 +878,13 @@ func _internal_updatePeerReactionSettings(account: Account, peerId: PeerId, reac
reactionLimitValue = maxReactionCount
}
return account.network.request(Api.functions.messages.setChatAvailableReactions(flags: flags, peer: inputPeer, availableReactions: mappedReactions, reactionsLimit: reactionLimitValue))
var paidEnabled: Api.Bool?
if let starsAllowed = reactionSettings.starsAllowed {
flags |= 1 << 1
paidEnabled = starsAllowed ? .boolTrue : .boolFalse
}
return account.network.request(Api.functions.messages.setChatAvailableReactions(flags: flags, peer: inputPeer, availableReactions: mappedReactions, reactionsLimit: reactionLimitValue, paidEnabled: paidEnabled))
|> map(Optional.init)
|> `catch` { error -> Signal<Api.Updates?, UpdatePeerAllowedReactionsError> in
if error.errorDescription == "CHAT_NOT_MODIFIED" {

View File

@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
public class Serialization: NSObject, MTSerialization {
public func currentLayer() -> UInt {
return 185
return 186
}
public func parseMessage(_ data: Data!) -> Any! {

View File

@ -182,7 +182,7 @@ extension Api.Chat {
return PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id))
case let .chatForbidden(id, _):
return PeerId(namespace: Namespaces.Peer.CloudGroup, id: PeerId.Id._internalFromInt64Value(id))
case let .channel(_, _, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .channel(_, _, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
return PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id))
case let .channelForbidden(_, id, _, _, _):
return PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(id))

View File

@ -636,10 +636,10 @@ public final class CachedChannelData: CachedPeerData {
self.reactionSettings = .known(reactionSettings)
} else if let legacyAllowedReactions = decoder.decodeOptionalStringArrayForKey("allowedReactions") {
let allowedReactions: PeerAllowedReactions = .limited(legacyAllowedReactions.map(MessageReaction.Reaction.builtin))
self.reactionSettings = .known(PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: nil))
self.reactionSettings = .known(PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: nil, starsAllowed: nil))
} else if let allowedReactions = decoder.decode(PeerAllowedReactions.self, forKey: "allowedReactionSet") {
let allowedReactions = allowedReactions
self.reactionSettings = .known(PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: nil))
self.reactionSettings = .known(PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: nil, starsAllowed: nil))
} else {
self.reactionSettings = .unknown
}

View File

@ -100,10 +100,12 @@ extension PeerAllowedReactions {
public final class PeerReactionSettings: Equatable, Codable {
public let allowedReactions: PeerAllowedReactions
public let maxReactionCount: Int32?
public let starsAllowed: Bool?
public init(allowedReactions: PeerAllowedReactions, maxReactionCount: Int32?) {
public init(allowedReactions: PeerAllowedReactions, maxReactionCount: Int32?, starsAllowed: Bool?) {
self.allowedReactions = allowedReactions
self.maxReactionCount = maxReactionCount
self.starsAllowed = starsAllowed
}
public static func ==(lhs: PeerReactionSettings, rhs: PeerReactionSettings) -> Bool {
@ -116,6 +118,9 @@ public final class PeerReactionSettings: Equatable, Codable {
if lhs.maxReactionCount != rhs.maxReactionCount {
return false
}
if lhs.starsAllowed != rhs.starsAllowed {
return false
}
return true
}
}
@ -266,10 +271,10 @@ public final class CachedGroupData: CachedPeerData {
self.reactionSettings = .known(reactionSettings)
} else if let legacyAllowedReactions = decoder.decodeOptionalStringArrayForKey("allowedReactions") {
let allowedReactions: PeerAllowedReactions = .limited(legacyAllowedReactions.map(MessageReaction.Reaction.builtin))
self.reactionSettings = .known(PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: nil))
self.reactionSettings = .known(PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: nil, starsAllowed: nil))
} else if let allowedReactions = decoder.decode(PeerAllowedReactions.self, forKey: "allowedReactionSet") {
let allowedReactions = allowedReactions
self.reactionSettings = .known(PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: nil))
self.reactionSettings = .known(PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: nil, starsAllowed: nil))
} else {
self.reactionSettings = .unknown
}

View File

@ -184,6 +184,7 @@ public extension PendingMessageActionType {
static let updateReaction = PendingMessageActionType(rawValue: 1)
static let sendScheduledMessageImmediately = PendingMessageActionType(rawValue: 2)
static let readReaction = PendingMessageActionType(rawValue: 3)
static let sendStarsReaction = PendingMessageActionType(rawValue: 4)
}
public let peerIdNamespacesWithInitialCloudMessageHoles = [Namespaces.Peer.CloudUser, Namespaces.Peer.CloudGroup, Namespaces.Peer.CloudChannel]

View File

@ -12,12 +12,15 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
public enum Reaction: Hashable, Comparable, Codable, PostboxCoding {
case builtin(String)
case custom(Int64)
case stars
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
if let value = try container.decodeIfPresent(String.self, forKey: "v") {
self = .builtin(value)
} else if let _ = try container.decodeIfPresent(Int64.self, forKey: "star") {
self = .stars
} else {
self = .custom(try container.decode(Int64.self, forKey: "cfid"))
}
@ -26,6 +29,8 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
public init(decoder: PostboxDecoder) {
if let value = decoder.decodeOptionalStringForKey("v") {
self = .builtin(value)
} else if let _ = decoder.decodeOptionalInt64ForKey("star") {
self = .stars
} else {
self = .custom(decoder.decodeInt64ForKey("cfid", orElse: 0))
}
@ -39,6 +44,8 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
try container.encode(value, forKey: "v")
case let .custom(fileId):
try container.encode(fileId, forKey: "cfid")
case .stars:
try container.encode(0 as Int64, forKey: "star")
}
}
@ -48,6 +55,8 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
encoder.encodeString(value, forKey: "v")
case let .custom(fileId):
encoder.encodeInt64(fileId, forKey: "cfid")
case .stars:
encoder.encodeInt64(0, forKey: "star")
}
}
@ -59,6 +68,8 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
return lhsValue < rhsValue
case .custom:
return true
case .stars:
return false
}
case let .custom(lhsValue):
switch rhs {
@ -66,6 +77,17 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
return false
case let .custom(rhsValue):
return lhsValue < rhsValue
case .stars:
return false
}
case .stars:
switch rhs {
case .builtin:
return true
case .custom:
return true
case .stars:
return false
}
}
}
@ -88,6 +110,8 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
public init(decoder: PostboxDecoder) {
if let value = decoder.decodeOptionalStringForKey("v") {
self.value = .builtin(value)
} else if let _ = decoder.decodeOptionalInt64ForKey("star") {
self.value = .stars
} else {
self.value = .custom(decoder.decodeInt64ForKey("cfid", orElse: 0))
}
@ -106,6 +130,8 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
if let value = try container.decodeIfPresent(String.self, forKey: "v") {
self.value = .builtin(value)
} else if let _ = try container.decodeIfPresent(Int64.self, forKey: "star") {
self.value = .stars
} else {
self.value = .custom(try container.decode(Int64.self, forKey: "cfid"))
}
@ -125,6 +151,8 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
encoder.encodeString(value, forKey: "v")
case let .custom(fileId):
encoder.encodeInt64(fileId, forKey: "cfid")
case .stars:
encoder.encodeInt64(0, forKey: "star")
}
encoder.encodeInt32(self.count, forKey: "c")
if let chosenOrder = self.chosenOrder {
@ -142,6 +170,8 @@ public struct MessageReaction: Equatable, PostboxCoding, Codable {
try container.encode(value, forKey: "v")
case let .custom(fileId):
try container.encode(fileId, forKey: "cfid")
case .stars:
try container.encode(0 as Int64, forKey: "star")
}
try container.encode(self.count, forKey: "c")
try container.encodeIfPresent(self.chosenOrder.flatMap(Int32.init), forKey: "cord")
@ -157,6 +187,8 @@ extension MessageReaction.Reaction {
self = .builtin(emoticon)
case let .reactionCustomEmoji(documentId):
self = .custom(documentId)
case .reactionPaid:
self = .stars
}
}
@ -166,6 +198,8 @@ extension MessageReaction.Reaction {
return .reactionEmoji(emoticon: value)
case let .custom(fileId):
return .reactionCustomEmoji(documentId: fileId)
case .stars:
return .reactionPaid
}
}
}
@ -191,6 +225,9 @@ public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
var typeId: UInt8 = 1
buffer.write(&typeId, offset: 0, length: 1)
buffer.write(&fileId, offset: 0, length: 8)
case .stars:
var typeId: UInt8 = 2
buffer.write(&typeId, offset: 0, length: 1)
}
return buffer
@ -231,6 +268,8 @@ public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
var fileId: Int64 = 0
readBuffer.read(&fileId, offset: 0, length: 8)
return .custom(fileId)
case 2:
return .stars
default:
return nil
}
@ -256,6 +295,8 @@ public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
public init(decoder: PostboxDecoder) {
if let value = decoder.decodeOptionalStringForKey("v") {
self.value = .builtin(value)
} else if let _ = decoder.decodeOptionalInt64ForKey("star") {
self.value = .stars
} else {
self.value = .custom(decoder.decodeInt64ForKey("cfid", orElse: 0))
}
@ -272,6 +313,8 @@ public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
encoder.encodeString(value, forKey: "v")
case let .custom(fileId):
encoder.encodeInt64(fileId, forKey: "cfid")
case .stars:
encoder.encodeInt64(0, forKey: "star")
}
encoder.encodeInt32(self.isLarge ? 1 : 0, forKey: "l")
encoder.encodeInt32(self.isUnseen ? 1 : 0, forKey: "u")
@ -306,6 +349,8 @@ public final class ReactionsMessageAttribute: Equatable, MessageAttribute {
if !result.contains(mediaId) {
result.append(mediaId)
}
case .stars:
break
}
}
@ -430,6 +475,8 @@ public final class PendingReactionsMessageAttribute: MessageAttribute {
if !result.contains(mediaId) {
result.append(mediaId)
}
case .stars:
break
}
}
@ -466,3 +513,35 @@ public final class PendingReactionsMessageAttribute: MessageAttribute {
encoder.encodeBool(self.isTags, forKey: "itag")
}
}
public final class PendingStarsReactionsMessageAttribute: MessageAttribute {
public let accountPeerId: PeerId?
public let count: Int32
public var associatedPeerIds: [PeerId] {
var peerIds: [PeerId] = []
if let accountPeerId = self.accountPeerId {
peerIds.append(accountPeerId)
}
return peerIds
}
public init(accountPeerId: PeerId?, count: Int32) {
self.accountPeerId = accountPeerId
self.count = count
}
required public init(decoder: PostboxDecoder) {
self.accountPeerId = decoder.decodeOptionalInt64ForKey("ap").flatMap(PeerId.init)
self.count = decoder.decodeInt32ForKey("cnt", orElse: 1)
}
public func encode(_ encoder: PostboxEncoder) {
if let accountPeerId = self.accountPeerId {
encoder.encodeInt64(accountPeerId.toInt64(), forKey: "ap")
} else {
encoder.encodeNil(forKey: "ap")
}
encoder.encodeInt32(self.count, forKey: "cnt")
}
}

View File

@ -154,9 +154,10 @@ public final class RecentEmojiItem: Codable, Equatable {
}
public struct RecentReactionItemId {
public enum Id : Hashable {
public enum Id: Hashable {
case custom(MediaId)
case builtin(String)
case stars
}
public let rawValue: MemoryBuffer
@ -184,6 +185,8 @@ public struct RecentReactionItemId {
assert(rawValue.length >= 1 + 2 + Int(length))
self.id = .builtin(String(data: Data(bytes: rawValue.memory.advanced(by: 1 + 2), count: Int(length)), encoding: .utf8) ?? ".")
} else if type == 2 {
self.id = .stars
} else {
assert(false)
self.id = .builtin(".")
@ -216,12 +219,23 @@ public struct RecentReactionItemId {
let _ = memcpy(self.rawValue.memory.advanced(by: 1 + 2), bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), bytes.count)
}
}
public init(_ id: Id) {
precondition(id == .stars)
self.id = id
self.rawValue = MemoryBuffer(memory: malloc(1)!, capacity: 1, length: 1, freeWhenDone: true)
var type: UInt8 = 2
memcpy(self.rawValue.memory.advanced(by: 0), &type, 1)
}
}
public final class RecentReactionItem: Codable, Equatable {
public enum Content: Equatable {
case custom(TelegramMediaFile)
case builtin(String)
case stars
}
public let content: Content
@ -232,6 +246,8 @@ public final class RecentReactionItem: Codable, Equatable {
return RecentReactionItemId(value)
case let .custom(file):
return RecentReactionItemId(file.fileId)
case .stars:
return RecentReactionItemId(.stars)
}
}
@ -244,6 +260,8 @@ public final class RecentReactionItem: Codable, Equatable {
if let mediaData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: "m") {
self.content = .custom(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: mediaData.data))))
} else if let _ = try container.decodeIfPresent(Int64.self, forKey: "star") {
self.content = .stars
} else {
self.content = .builtin(try container.decode(String.self, forKey: "s"))
}
@ -257,6 +275,8 @@ public final class RecentReactionItem: Codable, Equatable {
try container.encode(PostboxEncoder().encodeObjectToRawData(file), forKey: "m")
case let .builtin(string):
try container.encode(string, forKey: "s")
case .stars:
try container.encode(0 as Int64, forKey: "star")
}
}

View File

@ -18,3 +18,30 @@ public final class UpdateMessageReactionsAction: PendingMessageActionData {
}
}
}
public final class SendStarsReactionsAction: PendingMessageActionData {
public let randomId: Int64
public init(randomId: Int64) {
self.randomId = randomId
}
public init(decoder: PostboxDecoder) {
self.randomId = decoder.decodeInt64ForKey("id", orElse: 0)
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeInt64(self.randomId, forKey: "id")
}
public func isEqual(to: PendingMessageActionData) -> Bool {
if let other = to as? SendStarsReactionsAction {
if self.randomId != other.randomId {
return false
}
return true
} else {
return false
}
}
}

View File

@ -2254,7 +2254,7 @@ func _internal_groupCallDisplayAsAvailablePeers(accountPeerId: PeerId, network:
for chat in chats {
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
switch chat {
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _):
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _):
if let participantsCount = participantsCount {
subscribers[groupOrChannel.id] = participantsCount
}

View File

@ -505,6 +505,8 @@ public final class EngineStoryViewListContext {
return nil
case let .custom(fileId):
return transaction.getMedia(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)) as? TelegramMediaFile
case .stars:
return nil
}
}
)))
@ -696,6 +698,8 @@ public final class EngineStoryViewListContext {
reactionFile = nil
case let .custom(fileId):
reactionFile = transaction.getMedia(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)) as? TelegramMediaFile
case .stars:
reactionFile = nil
}
items.append(.view(Item.View(
peer: EnginePeer(peer),

View File

@ -138,7 +138,7 @@ func _internal_peerSendAsAvailablePeers(accountPeerId: PeerId, network: Network,
for chat in chats {
if let groupOrChannel = parsedPeers.get(chat.peerId) {
switch chat {
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _):
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _):
if let participantsCount = participantsCount {
subscribers[groupOrChannel.id] = participantsCount
}

View File

@ -331,7 +331,11 @@ public extension TelegramEngine {
isLarge: false,
storeAsRecentlyUsed: false,
add: true
).start()
).startStandalone()
}
public func sendStarsReaction(id: EngineMessage.Id, count: Int) {
let _ = sendStarsReactionsInteractively(account: self.account, messageId: id, count: count).startStandalone()
}
public func requestChatContextResults(botId: PeerId, peerId: PeerId, query: String, location: Signal<(Double, Double)?, NoError> = .single(nil), offset: String, incompleteResults: Bool = false, staleCachedResults: Bool = false) -> Signal<RequestChatContextResultsResult?, RequestChatContextResultsError> {

View File

@ -176,7 +176,7 @@ private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id
default:
break
}
signal = account.network.request(Api.functions.payments.getStarsTransactions(flags: flags, peer: inputPeer, offset: offset, limit: limit))
signal = account.network.request(Api.functions.payments.getStarsTransactions(flags: flags, subscriptionId: nil, peer: inputPeer, offset: offset, limit: limit))
} else {
signal = account.network.request(Api.functions.payments.getStarsStatus(peer: inputPeer))
}
@ -187,12 +187,12 @@ private func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id
|> mapToSignal { result -> Signal<InternalStarsStatus, RequestStarsStateError> in
return account.postbox.transaction { transaction -> InternalStarsStatus in
switch result {
case let .starsStatus(_, balance, history, nextOffset, chats, users):
case let .starsStatus(_, balance, _, _, _, history, nextOffset, chats, users):
let peers = AccumulatedPeers(chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: peers)
var parsedTransactions: [StarsContext.State.Transaction] = []
for entry in history {
for entry in history ?? [] {
if let parsedTransaction = StarsContext.State.Transaction(apiTransaction: entry, peerId: peerId != account.peerId ? peerId : nil, transaction: transaction) {
parsedTransactions.append(parsedTransaction)
}
@ -317,7 +317,7 @@ private final class StarsContextImpl {
private extension StarsContext.State.Transaction {
init?(apiTransaction: Api.StarsTransaction, peerId: EnginePeer.Id?, transaction: Transaction) {
switch apiTransaction {
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia):
case let .starsTransaction(apiFlags, id, stars, date, transactionPeer, title, description, photo, transactionDate, transactionUrl, _, messageId, extendedMedia, _):
let parsedPeer: StarsContext.State.Transaction.Peer
var paidMessageId: MessageId?
switch transactionPeer {
@ -889,7 +889,7 @@ func _internal_getStarsTransaction(accountPeerId: PeerId, postbox: Postbox, netw
}
|> mapToSignal { result -> Signal<StarsContext.State.Transaction?, NoError> in
return postbox.transaction { transaction -> StarsContext.State.Transaction? in
guard let result, case let .starsStatus(_, _, transactions, _, chats, users) = result, let matchingTransaction = transactions.first else {
guard let result, case let .starsStatus(_, _, _, _, _, transactions, _, chats, users) = result, let matchingTransaction = transactions?.first else {
return nil
}
let peers = AccumulatedPeers(chats: chats, users: users)

View File

@ -558,7 +558,7 @@ func _internal_adminedPublicChannels(account: Account, scope: AdminedPublicChann
case let .chats(apiChats):
chats = apiChats
for chat in apiChats {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _) = chat {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _) = chat {
subscriberCounts[chat.peerId] = participantsCount.flatMap(Int.init)
}
}
@ -630,7 +630,7 @@ func _internal_channelsForStories(account: Account) -> Signal<[Peer], NoError> {
if let peer = transaction.getPeer(chat.peerId) {
peers.append(peer)
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _) = chat, let participantsCount = participantsCount {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _) = chat, let participantsCount = participantsCount {
transaction.updatePeerCachedData(peerIds: Set([peer.id]), update: { _, current in
var current = current as? CachedChannelData ?? CachedChannelData()
var participantsSummary = current.participantsSummary

View File

@ -117,7 +117,7 @@ func _internal_requestRecommendedChannels(account: Account, peerId: EnginePeer.I
for chat in chats {
if let peer = transaction.getPeer(chat.peerId) {
peers.append(EnginePeer(peer))
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _) = chat, let participantsCount = participantsCount {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _) = chat, let participantsCount = participantsCount {
transaction.updatePeerCachedData(peerIds: Set([peer.id]), update: { _, current in
var current = current as? CachedChannelData ?? CachedChannelData()
var participantsSummary = current.participantsSummary

View File

@ -280,7 +280,7 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
var memberCounts: [PeerId: Int] = [:]
for chat in chats {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _) = chat {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _) = chat {
if let participantsCount = participantsCount {
memberCounts[chat.peerId] = Int(participantsCount)
}
@ -307,7 +307,7 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal<Cha
var memberCounts: [PeerId: Int] = [:]
for chat in chats {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _) = chat {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _) = chat {
if let participantsCount = participantsCount {
memberCounts[chat.peerId] = Int(participantsCount)
}
@ -621,7 +621,7 @@ func _internal_pollChatFolderUpdatesOnce(account: Account, folderId: Int32) -> S
var memberCounts: [ChatListFiltersState.ChatListFilterUpdates.MemberCount] = []
for chat in chats {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _) = chat {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _) = chat {
if let participantsCount = participantsCount {
memberCounts.append(ChatListFiltersState.ChatListFilterUpdates.MemberCount(id: chat.peerId, count: participantsCount))
}

View File

@ -31,7 +31,7 @@ func _internal_inactiveChannelList(network: Network) -> Signal<[InactiveChannel]
var participantsCounts: [PeerId: Int32] = [:]
for chat in chats {
switch chat {
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCountValue, _, _, _, _, _, _):
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCountValue, _, _, _, _, _, _, _):
if let participantsCountValue = participantsCountValue {
participantsCounts[chat.peerId] = participantsCountValue
}

View File

@ -44,7 +44,7 @@ func _internal_revokePersistentPeerExportedInvitation(account: Account, peerId:
if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
let flags: Int32 = (1 << 2)
if let _ = peer as? TelegramChannel {
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil, title: nil))
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil, title: nil, subscriptionPricing: nil))
|> retryRequest
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
return account.postbox.transaction { transaction -> ExportedInvitation? in
@ -61,7 +61,7 @@ func _internal_revokePersistentPeerExportedInvitation(account: Account, peerId:
}
}
} else if let _ = peer as? TelegramGroup {
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil, title: nil))
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: nil, usageLimit: nil, title: nil, subscriptionPricing: nil))
|> retryRequest
|> mapToSignal { result -> Signal<ExportedInvitation?, NoError> in
return account.postbox.transaction { transaction -> ExportedInvitation? in
@ -106,7 +106,7 @@ func _internal_createPeerExportedInvitation(account: Account, peerId: PeerId, ti
if let _ = title {
flags |= (1 << 4)
}
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: expireDate, usageLimit: usageLimit, title: title))
return account.network.request(Api.functions.messages.exportChatInvite(flags: flags, peer: inputPeer, expireDate: expireDate, usageLimit: usageLimit, title: title, subscriptionPricing: nil))
|> mapError { _ in return CreatePeerExportedInvitationError.generic }
|> map { result -> ExportedInvitation? in
return ExportedInvitation(apiExportedInvite: result)

View File

@ -106,7 +106,7 @@ func _internal_joinLinkInformation(_ hash: String, account: Account) -> Signal<E
|> mapToSignal { result -> Signal<ExternalJoiningChatState, JoinLinkInfoError> in
if let result = result {
switch result {
case let .chatInvite(flags, title, about, invitePhoto, participantsCount, participants, nameColor):
case let .chatInvite(flags, title, about, invitePhoto, participantsCount, participants, nameColor, _, _):
let photo = telegramMediaImageFromApiPhoto(invitePhoto).flatMap({ smallestImageRepresentation($0.representations) })
let flags: ExternalJoiningChatState.Invite.Flags = .init(isChannel: (flags & (1 << 0)) != 0, isBroadcast: (flags & (1 << 1)) != 0, isPublic: (flags & (1 << 2)) != 0, isMegagroup: (flags & (1 << 3)) != 0, requestNeeded: (flags & (1 << 6)) != 0, isVerified: (flags & (1 << 7)) != 0, isScam: (flags & (1 << 8)) != 0, isFake: (flags & (1 << 9)) != 0)
return .single(.invite(ExternalJoiningChatState.Invite(flags: flags, title: title, about: about, photoRepresentation: photo, participantsCount: participantsCount, participants: participants?.map({ EnginePeer(TelegramUser(user: $0)) }), nameColor: PeerNameColor(rawValue: nameColor))))

View File

@ -42,7 +42,7 @@ public func _internal_searchPeers(accountPeerId: PeerId, postbox: Postbox, netwo
for chat in chats {
if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) {
switch chat {
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _):
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _):
if let participantsCount = participantsCount {
subscribers[groupOrChannel.id] = participantsCount
}

View File

@ -367,7 +367,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
var subscriberCount: Int32?
for chat in chats {
if chat.peerId == channelPeerId {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _) = chat {
if case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCount, _, _, _, _, _, _, _) = chat {
subscriberCount = participantsCount
}
}
@ -509,7 +509,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
} else {
mappedAllowedReactions = .empty
}
let mappedReactionSettings = PeerReactionSettings(allowedReactions: mappedAllowedReactions, maxReactionCount: reactionsLimit)
let mappedReactionSettings = PeerReactionSettings(allowedReactions: mappedAllowedReactions, maxReactionCount: reactionsLimit, starsAllowed: nil)
return previous.withUpdatedParticipants(participants)
.withUpdatedExportedInvitation(exportedInvitation)
@ -556,10 +557,10 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
switch result {
case let .chatFull(fullChat, chats, users):
switch fullChat {
case let .channelFull(_, _, _, _, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)])
case .chatFull:
break
case let .channelFull(_, _, _, _, _, _, _, _, _, _, _, _, _, notifySettings, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: notifySettings)])
case .chatFull:
break
}
switch fullChat {
@ -691,7 +692,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
switch participantResult {
case let .channelParticipant(participant, _, _):
switch participant {
case let .channelParticipantSelf(flags, _, inviterId, invitedDate):
case let .channelParticipantSelf(_, _, inviterId, invitedDate, _):
invitedBy = PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(inviterId))
if (flags & (1 << 0)) != 0 {
invitedOn = invitedDate
@ -754,7 +755,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee
} else {
mappedAllowedReactions = .empty
}
let mappedReactionSettings = PeerReactionSettings(allowedReactions: mappedAllowedReactions, maxReactionCount: reactionsLimit)
let starsAllowed: Bool = (flags2 & (1 << 16)) != 0
let mappedReactionSettings = PeerReactionSettings(allowedReactions: mappedAllowedReactions, maxReactionCount: reactionsLimit, starsAllowed: starsAllowed)
let membersHidden = (flags2 & (1 << 2)) != 0
let forumViewAsMessages = (flags2 & (1 << 6)) != 0

View File

@ -180,7 +180,7 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal<Account
if let peer = parseTelegramGroupOrChannel(chat: chat) {
var participantCount: Int32? = nil
switch chat {
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCountValue, _, _, _, _, _, _):
case let .channel(_, _, _, _, _, _, _, _, _, _, _, _, participantsCountValue, _, _, _, _, _, _, _):
participantCount = participantsCountValue
default:
break

View File

@ -72,7 +72,7 @@ func updatePeers(transaction: Transaction, accountPeerId: PeerId, peers: Accumul
}
for (_, chat) in peers.chats {
switch chat {
case let .channel(flags, flags2, _, _, _, _, _, _, _, _, _, _, _, _, storiesMaxId, _, _, _, _):
case let .channel(flags, flags2, _, _, _, _, _, _, _, _, _, _, _, _, storiesMaxId, _, _, _, _, _):
let isMin = (flags & (1 << 12)) != 0
let storiesUnavailable = (flags2 & (1 << 3)) != 0

View File

@ -727,7 +727,7 @@ public class ChatMessageDateAndStatusNode: ASDisplayNode {
var animationFileId: Int64?
switch reaction.value {
case .builtin:
case .builtin, .stars:
if let availableReactions = arguments.availableReactions {
for availableReaction in availableReactions.reactions {
if availableReaction.value == reaction.value {

View File

@ -159,6 +159,15 @@ public final class MessageReactionButtonsNode: ASDisplayNode {
}
case let .custom(fileId):
animationFileId = fileId
case .stars:
if let availableReactions = availableReactions {
for availableReaction in availableReactions.reactions {
if availableReaction.value == reaction.value {
centerAnimation = availableReaction.centerAnimation
break
}
}
}
}
var peers: [EnginePeer] = []

View File

@ -318,6 +318,8 @@ public final class ChatMessageSelectionInputPanelNode: ChatInputPanelNode {
return .builtin(value)
case let .custom(fileId):
return .custom(fileId: fileId, file: nil)
case .stars:
return .stars
}
}
if let selectionState = presentationInterfaceState.interfaceState.selectionState {

View File

@ -1636,6 +1636,8 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
reactionText = "."
entities.append(MessageTextEntity(range: (text as NSString).length ..< (text as NSString).length + (reactionText as NSString).length, type: .CustomEmoji(stickerPack: nil, fileId: fileId)))
text.append(reactionText)
case .stars:
break
}
}
}

View File

@ -94,7 +94,7 @@ private final class BalanceComponent: CombinedComponent {
animationCache: context.component.context.animationCache,
animationRenderer: context.component.context.animationRenderer,
content: .animation(
content: .customEmoji(fileId: MessageReaction.starsReactionId),
content: .customEmoji(fileId: MessageReaction.starsReactionId), //TODO:release
size: iconSize,
placeholderColor: .gray,
themeColor: nil,

View File

@ -100,6 +100,13 @@ public final class ChatShareMessageTagView: UIView, UndoOverlayControllerAdditio
}
case let .custom(_, fileValue):
file = fileValue
case .stars:
for reaction in availableReactions.reactions {
if reaction.value == updateReaction.reaction {
file = reaction.centerAnimation
break
}
}
}
guard let file else {

View File

@ -10,13 +10,13 @@ public enum AllowedReactions {
case all
}
public func peerMessageAllowedReactions(context: AccountContext, message: Message) -> Signal<AllowedReactions?, NoError> {
public func peerMessageAllowedReactions(context: AccountContext, message: Message) -> Signal<(allowedReactions: AllowedReactions?, areStarsEnabled: Bool), NoError> {
if message.id.peerId == context.account.peerId {
return .single(.all)
return .single((.all, false))
}
if message.containsSecretMedia {
return .single(AllowedReactions.set(Set()))
return .single((AllowedReactions.set(Set()), false))
}
return combineLatest(
@ -26,7 +26,7 @@ public func peerMessageAllowedReactions(context: AccountContext, message: Messag
),
context.engine.stickers.availableReactions() |> take(1)
)
|> map { data, availableReactions -> AllowedReactions? in
|> map { data, availableReactions -> (allowedReactions: AllowedReactions?, areStarsEnabled: Bool) in
let (peer, reactionSettings) = data
let maxReactionCount: Int
@ -35,35 +35,41 @@ public func peerMessageAllowedReactions(context: AccountContext, message: Messag
} else {
maxReactionCount = 11
}
var areStarsEnabled: Bool = false
if let value = reactionSettings.knownValue?.starsAllowed {
areStarsEnabled = value
}
if let effectiveReactions = message.effectiveReactions(isTags: message.areReactionsTags(accountPeerId: context.account.peerId)), effectiveReactions.count >= maxReactionCount {
return .set(Set(effectiveReactions.map(\.value)))
return (.set(Set(effectiveReactions.map(\.value))), areStarsEnabled)
}
switch reactionSettings {
case .unknown:
if case let .channel(channel) = peer, case .broadcast = channel.info {
if let availableReactions = availableReactions {
return .set(Set(availableReactions.reactions.map(\.value)))
return (.set(Set(availableReactions.reactions.map(\.value))), areStarsEnabled)
} else {
return .set(Set())
return (.set(Set()), areStarsEnabled)
}
}
return .all
return (.all, areStarsEnabled)
case let .known(value):
switch value.allowedReactions {
case .all:
if case let .channel(channel) = peer, case .broadcast = channel.info {
if let availableReactions = availableReactions {
return .set(Set(availableReactions.reactions.map(\.value)))
return (.set(Set(availableReactions.reactions.map(\.value))), areStarsEnabled)
} else {
return .set(Set())
return (.set(Set()), areStarsEnabled)
}
}
return .all
return (.all, areStarsEnabled)
case let .limited(reactions):
return .set(Set(reactions))
return (.set(Set(reactions)), areStarsEnabled)
case .empty:
return .set(Set())
return (.set(Set()), areStarsEnabled)
}
}
}
@ -160,6 +166,8 @@ public func tagMessageReactions(context: AccountContext, subPeerId: EnginePeer.I
largeApplicationAnimation: nil,
isCustom: true
))
case .stars:
continue
}
}
@ -212,6 +220,33 @@ public func tagMessageReactions(context: AccountContext, subPeerId: EnginePeer.I
largeApplicationAnimation: nil,
isCustom: true
))
case .stars:
if let reaction = availableReactions?.reactions.first(where: { $0.value == .stars }) {
guard let centerAnimation = reaction.centerAnimation else {
continue
}
guard let aroundAnimation = reaction.aroundAnimation else {
continue
}
if existingIds.contains(reaction.value) {
continue
}
existingIds.insert(reaction.value)
result.append(ReactionItem(
reaction: ReactionItem.Reaction(rawValue: reaction.value),
appearAnimation: reaction.appearAnimation,
stillAnimation: reaction.selectAnimation,
listAnimation: centerAnimation,
largeListAnimation: reaction.activateAnimation,
applicationAnimation: aroundAnimation,
largeApplicationAnimation: reaction.effectAnimation,
isCustom: false
))
} else {
continue
}
}
}
}
@ -250,41 +285,28 @@ public func topMessageReactions(context: AccountContext, message: Message, subPe
}
}
let allowedReactionsWithFiles: Signal<(reactions: AllowedReactions, files: [Int64: TelegramMediaFile])?, NoError> = peerMessageAllowedReactions(context: context, message: message)
|> mapToSignal { allowedReactions -> Signal<(reactions: AllowedReactions, files: [Int64: TelegramMediaFile])?, NoError> in
let allowedReactionsWithFiles: Signal<(reactions: AllowedReactions, files: [Int64: TelegramMediaFile], areStarsEnabled: Bool)?, NoError> = peerMessageAllowedReactions(context: context, message: message)
|> mapToSignal { allowedReactions, areStarsEnabled -> Signal<(reactions: AllowedReactions, files: [Int64: TelegramMediaFile], areStarsEnabled: Bool)?, NoError> in
guard let allowedReactions = allowedReactions else {
return .single(nil)
}
if case let .set(reactions) = allowedReactions {
#if DEBUG
var reactions = reactions
if context.sharedContext.applicationBindings.appBuildType == .internal {
reactions.insert(.custom(MessageReaction.starsReactionId))
}
#endif
return context.engine.stickers.resolveInlineStickers(fileIds: reactions.compactMap { item -> Int64? in
switch item {
case .builtin:
return nil
case let .custom(fileId):
return fileId
case .stars:
return nil
}
})
|> map { files -> (reactions: AllowedReactions, files: [Int64: TelegramMediaFile]) in
return (.set(reactions), files)
|> map { files -> (reactions: AllowedReactions, files: [Int64: TelegramMediaFile], areStarsEnabled: Bool) in
return (.set(reactions), files, areStarsEnabled)
}
} else {
#if DEBUG
if context.sharedContext.applicationBindings.appBuildType == .internal {
return context.engine.stickers.resolveInlineStickers(fileIds: [MessageReaction.starsReactionId])
|> map { files -> (reactions: AllowedReactions, files: [Int64: TelegramMediaFile]) in
return (allowedReactions, files)
}
}
#endif
return .single((allowedReactions, [:]))
return .single((allowedReactions, [:], areStarsEnabled))
}
}
@ -302,25 +324,6 @@ public func topMessageReactions(context: AccountContext, message: Message, subPe
var result: [ReactionItem] = []
var existingIds = Set<MessageReaction.Reaction>()
#if DEBUG
if context.sharedContext.applicationBindings.appBuildType == .internal {
if let file = allowedReactionsAndFiles.files[MessageReaction.starsReactionId] {
existingIds.insert(.custom(MessageReaction.starsReactionId))
result.append(ReactionItem(
reaction: ReactionItem.Reaction(rawValue: .custom(file.fileId.id)),
appearAnimation: file,
stillAnimation: file,
listAnimation: file,
largeListAnimation: file,
applicationAnimation: nil,
largeApplicationAnimation: nil,
isCustom: true
))
}
}
#endif
for topReaction in topReactions {
switch topReaction.content {
case let .builtin(value):
@ -384,6 +387,8 @@ public func topMessageReactions(context: AccountContext, message: Message, subPe
largeApplicationAnimation: nil,
isCustom: true
))
case .stars:
break
}
}
@ -447,6 +452,28 @@ public func topMessageReactions(context: AccountContext, message: Message, subPe
isCustom: true
))
}
case .stars:
break
}
}
}
if allowedReactionsAndFiles.areStarsEnabled {
result.removeAll(where: { $0.reaction.rawValue == .stars })
if let reaction = availableReactions.reactions.first(where: { $0.value == .stars }) {
if let centerAnimation = reaction.centerAnimation, let aroundAnimation = reaction.aroundAnimation {
existingIds.insert(reaction.value)
result.insert(ReactionItem(
reaction: ReactionItem.Reaction(rawValue: reaction.value),
appearAnimation: reaction.appearAnimation,
stillAnimation: reaction.selectAnimation,
listAnimation: centerAnimation,
largeListAnimation: reaction.activateAnimation,
applicationAnimation: aroundAnimation,
largeApplicationAnimation: reaction.effectAnimation,
isCustom: false
), at: 0)
}
}
}

View File

@ -793,6 +793,10 @@ public extension EmojiPagerContentComponent {
}
case let .custom(file):
topReactionItems.append(EmojiComponentReactionItem(reaction: .custom(file.fileId.id), file: file))
case .stars:
if let reaction = availableReactions?.reactions.first(where: { $0.value == .stars }) {
topReactionItems.append(EmojiComponentReactionItem(reaction: .stars, file: reaction.selectAnimation))
}
}
}
}
@ -962,6 +966,22 @@ public extension EmojiPagerContentComponent {
} else {
icon = .none
}
case .stars:
if existingIds.contains(.stars) {
continue
}
existingIds.insert(.stars)
if let availableReactions = availableReactions, let availableReaction = availableReactions.reactions.first(where: { $0.value == .stars }) {
if let centerAnimation = availableReaction.centerAnimation {
animationFile = centerAnimation
} else {
continue
}
} else {
continue
}
icon = .none
}
var tintMode: Item.TintMode = .none
@ -1014,6 +1034,12 @@ public extension EmojiPagerContentComponent {
}
case let .custom(file):
topReactionItems.append(EmojiComponentReactionItem(reaction: .custom(file.fileId.id), file: file))
case .stars:
if let reaction = availableReactions?.reactions.first(where: { $0.value == .stars }) {
topReactionItems.append(EmojiComponentReactionItem(reaction: .stars, file: reaction.selectAnimation))
} else {
continue
}
}
}
}

View File

@ -8223,6 +8223,8 @@ private func allowedStoryReactions(context: AccountContext) -> Signal<[ReactionI
largeApplicationAnimation: nil,
isCustom: true
))
case .stars:
break
}
}

View File

@ -157,7 +157,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
allowedReactions = .empty
}
let reactionSettings = PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: self.allowedReactionCount >= 11 ? nil : Int32(self.allowedReactionCount))
let reactionSettings = PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: self.allowedReactionCount >= 11 ? nil : Int32(self.allowedReactionCount), starsAllowed: self.areStarsReactionsEnabled)
if self.appliedReactionSettings != reactionSettings {
if case .empty = allowedReactions {
@ -223,6 +223,8 @@ final class PeerAllowedReactionsScreenComponent: Component {
return true
case .builtin:
return false
case .stars:
return false
}
})
@ -248,7 +250,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
} else {
allowedReactions = .empty
}
let reactionSettings = PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: self.allowedReactionCount == 11 ? nil : Int32(self.allowedReactionCount))
let reactionSettings = PeerReactionSettings(allowedReactions: allowedReactions, maxReactionCount: self.allowedReactionCount == 11 ? nil : Int32(self.allowedReactionCount), starsAllowed: self.areStarsReactionsEnabled)
let applyDisposable = (component.context.engine.peers.updatePeerReactionSettings(peerId: component.peerId, reactionSettings: reactionSettings)
|> deliverOnMainQueue).start(error: { [weak self] error in
@ -362,10 +364,16 @@ final class PeerAllowedReactionsScreenComponent: Component {
self.appliedReactionSettings = component.initialContent.reactionSettings.flatMap { reactionSettings in
return PeerReactionSettings(
allowedReactions: reactionSettings.allowedReactions,
maxReactionCount: reactionSettings.maxReactionCount == 11 ? nil : reactionSettings.maxReactionCount
maxReactionCount: reactionSettings.maxReactionCount == 11 ? nil : reactionSettings.maxReactionCount,
starsAllowed: reactionSettings.starsAllowed
)
}
self.allowedReactionCount = (component.initialContent.reactionSettings?.maxReactionCount).flatMap(Int.init) ?? 11
if let value = component.initialContent.reactionSettings?.starsAllowed {
self.areStarsReactionsEnabled = value
} else {
self.areStarsReactionsEnabled = component.initialContent.isStarReactionAvailable
}
}
var caretPosition = self.caretPosition ?? enabledReactions.count
caretPosition = max(0, min(enabledReactions.count, caretPosition))
@ -443,6 +451,8 @@ final class PeerAllowedReactionsScreenComponent: Component {
return true
case .builtin:
return false
case .stars:
return false
}
})
@ -868,7 +878,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
}
contentHeight += reactionCountSectionSize.height
if !"".isEmpty {
if component.initialContent.isStarReactionAvailable {
contentHeight += 32.0
let paidReactionsSection: ComponentView<Empty>
@ -926,7 +936,7 @@ final class PeerAllowedReactionsScreenComponent: Component {
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListSwitchItemComponent(
theme: environment.theme,
title: "Enable Paid Reactions",
value: areStarsReactionsEnabled,
value: self.areStarsReactionsEnabled,
valueUpdated: { [weak self] value in
guard let self else {
return
@ -1049,6 +1059,8 @@ final class PeerAllowedReactionsScreenComponent: Component {
return true
case .builtin:
return false
case .stars:
return false
}
}).count : 0
@ -1231,17 +1243,20 @@ public class PeerAllowedReactionsScreen: ViewControllerComponentContainer {
public let enabledReactions: [EmojiComponentReactionItem]
public let availableReactions: AvailableReactions?
public let reactionSettings: PeerReactionSettings?
public let isStarReactionAvailable: Bool
init(
isEnabled: Bool,
enabledReactions: [EmojiComponentReactionItem],
availableReactions: AvailableReactions?,
reactionSettings: PeerReactionSettings?
reactionSettings: PeerReactionSettings?,
isStarReactionAvailable: Bool
) {
self.isEnabled = isEnabled
self.enabledReactions = enabledReactions
self.availableReactions = availableReactions
self.reactionSettings = reactionSettings
self.isStarReactionAvailable = isStarReactionAvailable
}
public static func ==(lhs: Content, rhs: Content) -> Bool {
@ -1260,6 +1275,9 @@ public class PeerAllowedReactionsScreen: ViewControllerComponentContainer {
if lhs.reactionSettings != rhs.reactionSettings {
return false
}
if lhs.isStarReactionAvailable != rhs.isStarReactionAvailable {
return false
}
return true
}
}
@ -1370,7 +1388,7 @@ public class PeerAllowedReactionsScreen: ViewControllerComponentContainer {
}
}
return Content(isEnabled: isEnabled, enabledReactions: result, availableReactions: availableReactions, reactionSettings: reactionSettings)
return Content(isEnabled: isEnabled, enabledReactions: result, availableReactions: availableReactions, reactionSettings: reactionSettings, isStarReactionAvailable: cachedData.flags.contains(.paidMediaAllowed))
}
}
|> distinctUntilChanged

View File

@ -338,6 +338,15 @@ public class ItemListReactionItemNode: ListViewItemNode, ItemListItemNode {
}
case let .custom(fileId):
animationContent = .customEmoji(fileId: fileId)
case .stars:
if let availableReactions = item.availableReactions {
for reaction in availableReactions.reactions {
if reaction.value == item.reaction {
animationContent = .file(file: reaction.selectAnimation)
break
}
}
}
}

View File

@ -307,6 +307,13 @@ public func quickReactionSetupController(
}
case let .custom(fileId):
currentSelectedFileId = MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)
case .stars:
if let availableReactions = availableReactions {
if let reaction = availableReactions.reactions.first(where: { $0.value == settings.quickReaction }) {
currentSelectedFileId = reaction.selectAnimation.fileId
break
}
}
}
var selectedItems = Set<MediaId>()

View File

@ -207,6 +207,31 @@ class ReactionChatPreviewItemNode: ListViewItemNode {
strongSelf.beginReactionAnimation(reactionItem: reactionItem)
}
})
case .stars:
for reaction in availableReactions.reactions {
guard let centerAnimation = reaction.centerAnimation else {
continue
}
guard let aroundAnimation = reaction.aroundAnimation else {
continue
}
if reaction.value == updatedReaction {
let reactionItem = ReactionItem(
reaction: ReactionItem.Reaction(rawValue: reaction.value),
appearAnimation: reaction.appearAnimation,
stillAnimation: reaction.selectAnimation,
listAnimation: centerAnimation,
largeListAnimation: reaction.activateAnimation,
applicationAnimation: aroundAnimation,
largeApplicationAnimation: reaction.effectAnimation,
isCustom: false
)
self.beginReactionAnimation(reactionItem: reactionItem)
break
}
}
}
}
}

View File

@ -987,6 +987,9 @@ public final class PeerListItemComponent: Component {
self.file = file
self.updateReactionLayer()
})
case .stars:
self.file = reaction.file
self.updateReactionLayer()
}
} else {
self.file = nil

View File

@ -1859,6 +1859,8 @@ public func preloadStoryMedia(context: AccountContext, info: StoryPreloadInfo) -
if !customReactions.contains(fileId) {
customReactions.append(fileId)
}
case .stars:
break
}
}
if !builtinReactions.isEmpty {
@ -2090,6 +2092,8 @@ public func waitUntilStoryMediaPreloaded(context: AccountContext, peerId: Engine
if !customReactions.contains(fileId) {
customReactions.append(fileId)
}
case .stars:
break
}
}
}

View File

@ -2198,6 +2198,8 @@ func allowedStoryReactions(context: AccountContext) -> Signal<[ReactionItem], No
largeApplicationAnimation: nil,
isCustom: true
))
case .stars:
break
}
}

View File

@ -98,6 +98,8 @@ public func storyPreviewWithAddedReactions(
if !customFileIds.contains(fileId) {
customFileIds.append(fileId)
}
case .stars:
break
}
}
}
@ -361,6 +363,15 @@ final class StoryItemOverlaysView: UIView {
})
}
}
case .stars:
if let availableReactions {
for reactionItem in availableReactions.reactionItems {
if reactionItem.reaction.rawValue == reaction {
file = reactionItem.stillAnimation
break
}
}
}
}
}

View File

@ -1745,6 +1745,15 @@ public final class StoryItemSetContainerComponent: Component {
}
case let .custom(fileId):
animationFileId = fileId
case .stars:
if let availableReactions = component.availableReactions {
for availableReaction in availableReactions.reactionItems {
if availableReaction.reaction.rawValue == value {
centerAnimation = availableReaction.listAnimation
break
}
}
}
}
if animationFileId == nil && centerAnimation == nil {
@ -2944,6 +2953,15 @@ public final class StoryItemSetContainerComponent: Component {
}
case let .custom(fileId):
animationFileId = fileId
case .stars:
if let availableReactions = component.availableReactions {
for availableReaction in availableReactions.reactionItems {
if availableReaction.reaction.rawValue == value {
centerAnimation = availableReaction.listAnimation
break
}
}
}
}
if animationFileId == nil && centerAnimation == nil {
@ -4564,7 +4582,7 @@ public final class StoryItemSetContainerComponent: Component {
standaloneReactionAnimation.frame = self.bounds
self.addSubview(standaloneReactionAnimation.view)
}, completion: { [weak targetView, weak reactionContextNode] in
}, onHit: nil, completion: { [weak targetView, weak reactionContextNode] in
targetView?.removeFromSuperview()
if let reactionContextNode {
reactionContextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak reactionContextNode] _ in
@ -4602,6 +4620,8 @@ public final class StoryItemSetContainerComponent: Component {
}
}
}
case .stars:
break
}
let message: EnqueueMessage = .message(
@ -4748,7 +4768,7 @@ public final class StoryItemSetContainerComponent: Component {
standaloneReactionAnimation.frame = self.bounds
self.componentContainerView.addSubview(standaloneReactionAnimation.view)
}, completion: { [weak reactionContextNode] in
}, onHit: nil, completion: { [weak reactionContextNode] in
if let reactionContextNode {
reactionContextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak reactionContextNode] _ in
reactionContextNode?.view.removeFromSuperview()

View File

@ -3577,6 +3577,15 @@ final class StoryItemSetContainerSendMessage {
animateWithReactionItem(reactionItem)
}
})
case .stars:
if let availableReactions = component.availableReactions {
for reactionItem in availableReactions.reactionItems {
if reactionItem.reaction.rawValue == reaction {
animateWithReactionItem(reactionItem)
break
}
}
}
}
}
}

View File

@ -569,6 +569,15 @@ final class StoryItemSetViewListComponent: Component {
if case let .view(view) = item {
animationFile = view.reactionFile
}
case .stars:
if let availableReactions = component.availableReactions {
for availableReaction in availableReactions.reactionItems {
if availableReaction.reaction.rawValue == reaction {
animationFile = availableReaction.listAnimation
break
}
}
}
}
return PeerListItemComponent.Reaction(
reaction: reaction,

View File

@ -1627,7 +1627,7 @@ extension ChatControllerImpl {
var reactionItem: ReactionItem?
switch updatedReaction {
case .builtin:
case .builtin, .stars:
for reaction in availableReactions.reactions {
guard let centerAnimation = reaction.centerAnimation else {
continue

View File

@ -52,15 +52,12 @@ extension ChatControllerImpl {
peerMessageSelectedReactions(context: self.context, message: topMessage),
topMessageReactions(context: self.context, message: topMessage, subPeerId: self.chatLocation.threadId.flatMap(EnginePeer.Id.init)),
ApplicationSpecificNotice.getChatTextSelectionTips(accountManager: self.context.sharedContext.accountManager)
).startStandalone(next: { [weak self] peer, actions, allowedReactions, selectedReactions, topReactions, chatTextSelectionTips in
).startStandalone(next: { [weak self] peer, actions, allowedReactionsAndStars, selectedReactions, topReactions, chatTextSelectionTips in
guard let self else {
return
}
/*var hasPremium = false
if case let .user(user) = peer, user.isPremium {
hasPremium = true
}*/
var (allowedReactions, _) = allowedReactionsAndStars
var actions = actions
switch actions.content {
@ -72,7 +69,6 @@ extension ChatControllerImpl {
break
}
var allowedReactions = allowedReactions
if allowedReactions != nil, case let .customChatContents(customChatContents) = self.presentationInterfaceState.subject {
if case let .hashTagSearch(publicPosts) = customChatContents.kind, publicPosts {
allowedReactions = nil
@ -335,44 +331,13 @@ extension ChatControllerImpl {
controller?.view.endEditing(true)
let chosenReaction: MessageReaction.Reaction = chosenUpdatedReaction.reaction
let currentReactions = mergedMessageReactions(attributes: message.attributes, isTags: message.areReactionsTags(accountPeerId: self.context.account.peerId))?.reactions ?? []
var updatedReactions: [MessageReaction.Reaction] = currentReactions.filter(\.isSelected).map(\.value)
var removedReaction: MessageReaction.Reaction?
var isFirst = false
if let index = updatedReactions.firstIndex(where: { $0 == chosenReaction }) {
removedReaction = chosenReaction
updatedReactions.remove(at: index)
} else {
updatedReactions.append(chosenReaction)
isFirst = !currentReactions.contains(where: { $0.value == chosenReaction })
}
if message.areReactionsTags(accountPeerId: self.context.account.peerId) {
if removedReaction == nil, !topReactions.contains(where: { $0.reaction.rawValue == chosenReaction }) {
if !self.presentationInterfaceState.isPremium {
controller?.premiumReactionsSelected?()
return
}
}
} else {
if removedReaction == nil, case .custom = chosenReaction {
if let peer = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = peer.info {
} else {
if !self.presentationInterfaceState.isPremium {
controller?.premiumReactionsSelected?()
return
}
}
}
}
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item {
if item.message.id == message.id {
if removedReaction == nil && !updatedReactions.isEmpty {
if case .stars = chosenUpdatedReaction.reaction {
let isFirst = !"".isEmpty
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item {
if item.message.id == message.id {
let chosenReaction: MessageReaction.Reaction = .stars
itemNode.awaitingAppliedReaction = (chosenReaction, { [weak self, weak itemNode] in
guard let self, let controller = controller else {
return
@ -392,61 +357,139 @@ extension ChatControllerImpl {
self.chatDisplayNode.messageTransitionNode.addMessageStandaloneReactionAnimation(messageId: item.message.id, standaloneReactionAnimation: standaloneReactionAnimation)
standaloneReactionAnimation.frame = self.chatDisplayNode.bounds
self.chatDisplayNode.addSubnode(standaloneReactionAnimation)
}, completion: { [weak self, weak itemNode, weak targetView] in
guard let self, let itemNode, let targetView else {
}, onHit: { [weak self, weak itemNode] in
guard let self else {
return
}
if self.chatLocation.peerId == self.context.account.peerId {
let _ = (ApplicationSpecificNotice.getSavedMessageTagLabelSuggestion(accountManager: self.context.sharedContext.accountManager)
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak targetView, weak itemNode] value in
guard let self, let targetView, let itemNode else {
return
}
if value >= 3 {
return
}
let _ = itemNode
let rect = self.chatDisplayNode.view.convert(targetView.bounds, from: targetView).insetBy(dx: -8.0, dy: -8.0)
let tooltipScreen = TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: .plain(text: self.presentationData.strings.Chat_TooltipAddTagLabel), location: .point(rect, .bottom), displayDuration: .manual, shouldDismissOnTouch: { _, _ in
return .dismiss(consume: false)
})
self.present(tooltipScreen, in: .current)
let _ = ApplicationSpecificNotice.incrementSavedMessageTagLabelSuggestion(accountManager: self.context.sharedContext.accountManager).startStandalone()
})
if let itemNode = itemNode, let targetView = itemNode.targetReactionView(value: chosenReaction) {
self.chatDisplayNode.wrappingNode.triggerRipple(at: targetView.convert(targetView.bounds.center, to: self.chatDisplayNode.view))
}
})
}, completion: {})
} else {
controller.dismiss()
}
})
} else {
itemNode.awaitingAppliedReaction = (nil, {
controller?.dismiss()
})
}
}
}
}
let mappedUpdatedReactions = updatedReactions.map { reaction -> UpdateMessageReaction in
switch reaction {
case let .builtin(value):
return .builtin(value)
case let .custom(fileId):
var customFile: TelegramMediaFile?
if case let .custom(customFileId, file) = chosenUpdatedReaction, fileId == customFileId {
customFile = file
}
return .custom(fileId: fileId, file: customFile)
let _ = sendStarsReactionsInteractively(account: self.context.account, messageId: message.id, count: 1).startStandalone()
} else {
let chosenReaction: MessageReaction.Reaction = chosenUpdatedReaction.reaction
let currentReactions = mergedMessageReactions(attributes: message.attributes, isTags: message.areReactionsTags(accountPeerId: self.context.account.peerId))?.reactions ?? []
var updatedReactions: [MessageReaction.Reaction] = currentReactions.filter(\.isSelected).map(\.value)
var removedReaction: MessageReaction.Reaction?
var isFirst = false
if let index = updatedReactions.firstIndex(where: { $0 == chosenReaction }) {
removedReaction = chosenReaction
updatedReactions.remove(at: index)
} else {
updatedReactions.append(chosenReaction)
isFirst = !currentReactions.contains(where: { $0.value == chosenReaction })
}
if message.areReactionsTags(accountPeerId: self.context.account.peerId) {
if removedReaction == nil, !topReactions.contains(where: { $0.reaction.rawValue == chosenReaction }) {
if !self.presentationInterfaceState.isPremium {
controller?.premiumReactionsSelected?()
return
}
}
} else {
if removedReaction == nil, case .custom = chosenReaction {
if let peer = self.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, case .broadcast = peer.info {
} else {
if !self.presentationInterfaceState.isPremium {
controller?.premiumReactionsSelected?()
return
}
}
}
}
self.chatDisplayNode.historyNode.forEachItemNode { itemNode in
if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item {
if item.message.id == message.id {
if removedReaction == nil && !updatedReactions.isEmpty {
itemNode.awaitingAppliedReaction = (chosenReaction, { [weak self, weak itemNode] in
guard let self, let controller = controller else {
return
}
if let itemNode = itemNode, let targetView = itemNode.targetReactionView(value: chosenReaction) {
self.chatDisplayNode.messageTransitionNode.addMessageContextController(messageId: item.message.id, contextController: controller)
var hideTargetButton: UIView?
if isFirst {
hideTargetButton = targetView.superview
}
controller.dismissWithReaction(value: chosenReaction, targetView: targetView, hideNode: true, animateTargetContainer: hideTargetButton, addStandaloneReactionAnimation: { [weak self] standaloneReactionAnimation in
guard let self else {
return
}
self.chatDisplayNode.messageTransitionNode.addMessageStandaloneReactionAnimation(messageId: item.message.id, standaloneReactionAnimation: standaloneReactionAnimation)
standaloneReactionAnimation.frame = self.chatDisplayNode.bounds
self.chatDisplayNode.addSubnode(standaloneReactionAnimation)
}, onHit: nil, completion: { [weak self, weak itemNode, weak targetView] in
guard let self, let itemNode, let targetView else {
return
}
if self.chatLocation.peerId == self.context.account.peerId {
let _ = (ApplicationSpecificNotice.getSavedMessageTagLabelSuggestion(accountManager: self.context.sharedContext.accountManager)
|> take(1)
|> deliverOnMainQueue).startStandalone(next: { [weak self, weak targetView, weak itemNode] value in
guard let self, let targetView, let itemNode else {
return
}
if value >= 3 {
return
}
let _ = itemNode
let rect = self.chatDisplayNode.view.convert(targetView.bounds, from: targetView).insetBy(dx: -8.0, dy: -8.0)
let tooltipScreen = TooltipScreen(account: self.context.account, sharedContext: self.context.sharedContext, text: .plain(text: self.presentationData.strings.Chat_TooltipAddTagLabel), location: .point(rect, .bottom), displayDuration: .manual, shouldDismissOnTouch: { _, _ in
return .dismiss(consume: false)
})
self.present(tooltipScreen, in: .current)
let _ = ApplicationSpecificNotice.incrementSavedMessageTagLabelSuggestion(accountManager: self.context.sharedContext.accountManager).startStandalone()
})
}
})
} else {
controller.dismiss()
}
})
} else {
itemNode.awaitingAppliedReaction = (nil, {
controller?.dismiss()
})
}
}
}
}
let mappedUpdatedReactions = updatedReactions.map { reaction -> UpdateMessageReaction in
switch reaction {
case let .builtin(value):
return .builtin(value)
case let .custom(fileId):
var customFile: TelegramMediaFile?
if case let .custom(customFileId, file) = chosenUpdatedReaction, fileId == customFileId {
customFile = file
}
return .custom(fileId: fileId, file: customFile)
case .stars:
return .stars
}
}
let _ = updateMessageReactionsInteractively(account: self.context.account, messageIds: [message.id], reactions: mappedUpdatedReactions, isLarge: isLarge, storeAsRecentlyUsed: true).startStandalone()
}
let _ = updateMessageReactionsInteractively(account: self.context.account, messageIds: [message.id], reactions: mappedUpdatedReactions, isLarge: isLarge, storeAsRecentlyUsed: true).startStandalone()
}
self.forEachController({ controller in

View File

@ -19,7 +19,7 @@ func peerMessageSelectedReactions(context: AccountContext, message: Message) ->
}
reactions.insert(reaction.value)
switch reaction.value {
case .builtin:
case .builtin, .stars:
if let availableReaction = availableReactions?.reactions.first(where: { $0.value == reaction.value }) {
result.insert(availableReaction.selectAnimation.fileId)
}

View File

@ -1510,6 +1510,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
chosenReaction = .builtin(value)
case let .custom(fileId):
chosenReaction = .custom(fileId)
case .stars:
chosenReaction = .stars
}
case let .reaction(value):
switch value {
@ -1517,6 +1519,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
chosenReaction = .builtin(value)
case let .custom(fileId):
chosenReaction = .custom(fileId)
case .stars:
chosenReaction = .stars
}
}
@ -1540,7 +1544,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
let _ = (peerMessageAllowedReactions(context: strongSelf.context, message: message)
|> deliverOnMainQueue).startStandalone(next: { allowedReactions in
|> deliverOnMainQueue).startStandalone(next: { allowedReactions, _ in
guard let strongSelf = self else {
return
}
@ -1564,6 +1568,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
chosenReaction = .builtin(value)
case let .custom(fileId):
chosenReaction = .custom(fileId)
case .stars:
chosenReaction = .stars
}
case let .reaction(value):
switch value {
@ -1571,6 +1577,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
chosenReaction = .builtin(value)
case let .custom(fileId):
chosenReaction = .custom(fileId)
case .stars:
chosenReaction = .stars
}
}
@ -1578,48 +1586,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
var removedReaction: MessageReaction.Reaction?
var messageAlreadyHasThisReaction = false
let currentReactions = mergedMessageReactions(attributes: message.attributes, isTags: message.areReactionsTags(accountPeerId: context.account.peerId))?.reactions ?? []
var updatedReactions: [MessageReaction.Reaction] = currentReactions.filter(\.isSelected).map(\.value)
if let index = updatedReactions.firstIndex(where: { $0 == chosenReaction }) {
removedReaction = chosenReaction
updatedReactions.remove(at: index)
} else {
updatedReactions.append(chosenReaction)
messageAlreadyHasThisReaction = currentReactions.contains(where: { $0.value == chosenReaction })
}
if removedReaction == nil {
if !canAddMessageReactions(message: message) {
itemNode.openMessageContextMenu()
return
}
if strongSelf.context.sharedContext.immediateExperimentalUISettings.disableQuickReaction {
itemNode.openMessageContextMenu()
return
}
guard let allowedReactions = allowedReactions else {
itemNode.openMessageContextMenu()
return
}
switch allowedReactions {
case let .set(set):
if !messageAlreadyHasThisReaction && updatedReactions.contains(where: { !set.contains($0) }) {
itemNode.openMessageContextMenu()
return
}
case .all:
break
}
}
if removedReaction == nil && !updatedReactions.isEmpty {
if case .stars = chosenReaction {
if strongSelf.selectPollOptionFeedback == nil {
strongSelf.selectPollOptionFeedback = HapticFeedback()
}
@ -1633,7 +1600,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var reactionItem: ReactionItem?
switch chosenReaction {
case .builtin:
case .builtin, .stars:
for reaction in availableReactions.reactions {
guard let centerAnimation = reaction.centerAnimation else {
continue
@ -1694,6 +1661,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
standaloneReactionAnimation.frame = strongSelf.chatDisplayNode.bounds
strongSelf.chatDisplayNode.addSubnode(standaloneReactionAnimation)
},
onHit: { [weak itemNode] in
guard let strongSelf = self else {
return
}
if let itemNode = itemNode, let targetView = itemNode.targetReactionView(value: chosenReaction) {
strongSelf.chatDisplayNode.wrappingNode.triggerRipple(at: targetView.convert(targetView.bounds.center, to: strongSelf.chatDisplayNode.view))
}
},
completion: { [weak standaloneReactionAnimation] in
standaloneReactionAnimation?.removeFromSupernode()
}
@ -1701,78 +1676,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
})
} else {
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts(itemNode: itemNode)
if let removedReaction = removedReaction, let targetView = itemNode.targetReactionView(value: removedReaction), shouldDisplayInlineDateReactions(message: message, isPremium: strongSelf.presentationInterfaceState.isPremium, forceInline: false) {
var hideRemovedReaction: Bool = false
if let reactions = mergedMessageReactions(attributes: message.attributes, isTags: message.areReactionsTags(accountPeerId: context.account.peerId)) {
for reaction in reactions.reactions {
if reaction.value == removedReaction {
hideRemovedReaction = reaction.count == 1
break
}
}
}
let standaloneDismissAnimation = StandaloneDismissReactionAnimation()
standaloneDismissAnimation.frame = strongSelf.chatDisplayNode.bounds
strongSelf.chatDisplayNode.addSubnode(standaloneDismissAnimation)
standaloneDismissAnimation.animateReactionDismiss(sourceView: targetView, hideNode: hideRemovedReaction, isIncoming: message.effectivelyIncoming(strongSelf.context.account.peerId), completion: { [weak standaloneDismissAnimation] in
standaloneDismissAnimation?.removeFromSupernode()
})
}
}
let mappedUpdatedReactions = updatedReactions.map { reaction -> UpdateMessageReaction in
switch reaction {
case let .builtin(value):
return .builtin(value)
case let .custom(fileId):
return .custom(fileId: fileId, file: nil)
}
}
if !strongSelf.presentationInterfaceState.isPremium && mappedUpdatedReactions.count > strongSelf.context.userLimits.maxReactionsPerMessage {
let _ = (ApplicationSpecificNotice.incrementMultipleReactionsSuggestion(accountManager: strongSelf.context.sharedContext.accountManager)
|> deliverOnMainQueue).startStandalone(next: { [weak self] count in
guard let self else {
return
}
if count < 1 {
let context = self.context
let controller = UndoOverlayController(
presentationData: self.presentationData,
content: .premiumPaywall(title: nil, text: self.presentationData.strings.Chat_Reactions_MultiplePremiumTooltip, customUndoText: nil, timeout: nil, linkAction: nil),
elevatedLayout: false,
action: { [weak self] action in
if case .info = action {
if let self {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .reactions, forceDark: false, dismissed: nil)
self.push(controller)
}
}
return true
}
)
self.present(controller, in: .current)
}
})
}
let _ = updateMessageReactionsInteractively(account: strongSelf.context.account, messageIds: [message.id], reactions: mappedUpdatedReactions, isLarge: false, storeAsRecentlyUsed: false).startStandalone()
#if DEBUG
if strongSelf.context.sharedContext.applicationBindings.appBuildType == .internal {
if mappedUpdatedReactions.contains(where: {
if case let .custom(fileId, _) = $0, fileId == MessageReaction.starsReactionId {
return true
} else {
return false
}
}) {
let _ = sendStarsReactionsInteractively(account: strongSelf.context.account, messageId: message.id, count: 1).startStandalone()
if !"".isEmpty {
let _ = (strongSelf.context.engine.stickers.resolveInlineStickers(fileIds: [MessageReaction.starsReactionId])
|> deliverOnMainQueue).start(next: { [weak strongSelf, weak itemNode] files in
|> deliverOnMainQueue).start(next: { [weak strongSelf, weak itemNode] files in
guard let strongSelf, let file = files[MessageReaction.starsReactionId] else {
return
}
@ -1786,8 +1695,193 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
})
}
} else {
var removedReaction: MessageReaction.Reaction?
var messageAlreadyHasThisReaction = false
let currentReactions = mergedMessageReactions(attributes: message.attributes, isTags: message.areReactionsTags(accountPeerId: context.account.peerId))?.reactions ?? []
var updatedReactions: [MessageReaction.Reaction] = currentReactions.filter(\.isSelected).map(\.value)
if let index = updatedReactions.firstIndex(where: { $0 == chosenReaction }) {
removedReaction = chosenReaction
updatedReactions.remove(at: index)
} else {
updatedReactions.append(chosenReaction)
messageAlreadyHasThisReaction = currentReactions.contains(where: { $0.value == chosenReaction })
}
if removedReaction == nil {
if !canAddMessageReactions(message: message) {
itemNode.openMessageContextMenu()
return
}
if strongSelf.context.sharedContext.immediateExperimentalUISettings.disableQuickReaction {
itemNode.openMessageContextMenu()
return
}
guard let allowedReactions = allowedReactions else {
itemNode.openMessageContextMenu()
return
}
switch allowedReactions {
case let .set(set):
if !messageAlreadyHasThisReaction && updatedReactions.contains(where: { !set.contains($0) }) {
itemNode.openMessageContextMenu()
return
}
case .all:
break
}
}
if removedReaction == nil && !updatedReactions.isEmpty {
if strongSelf.selectPollOptionFeedback == nil {
strongSelf.selectPollOptionFeedback = HapticFeedback()
}
strongSelf.selectPollOptionFeedback?.tap()
itemNode.awaitingAppliedReaction = (chosenReaction, { [weak itemNode] in
guard let strongSelf = self else {
return
}
if let itemNode = itemNode, let item = itemNode.item, let availableReactions = item.associatedData.availableReactions, let targetView = itemNode.targetReactionView(value: chosenReaction) {
var reactionItem: ReactionItem?
switch chosenReaction {
case .builtin, .stars:
for reaction in availableReactions.reactions {
guard let centerAnimation = reaction.centerAnimation else {
continue
}
guard let aroundAnimation = reaction.aroundAnimation else {
continue
}
if reaction.value == chosenReaction {
reactionItem = ReactionItem(
reaction: ReactionItem.Reaction(rawValue: reaction.value),
appearAnimation: reaction.appearAnimation,
stillAnimation: reaction.selectAnimation,
listAnimation: centerAnimation,
largeListAnimation: reaction.activateAnimation,
applicationAnimation: aroundAnimation,
largeApplicationAnimation: reaction.effectAnimation,
isCustom: false
)
break
}
}
case let .custom(fileId):
if let itemFile = item.message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] as? TelegramMediaFile {
reactionItem = ReactionItem(
reaction: ReactionItem.Reaction(rawValue: chosenReaction),
appearAnimation: itemFile,
stillAnimation: itemFile,
listAnimation: itemFile,
largeListAnimation: itemFile,
applicationAnimation: nil,
largeApplicationAnimation: nil,
isCustom: true
)
}
}
if let reactionItem = reactionItem {
let standaloneReactionAnimation = StandaloneReactionAnimation(genericReactionEffect: strongSelf.chatDisplayNode.historyNode.takeGenericReactionEffect())
strongSelf.chatDisplayNode.messageTransitionNode.addMessageStandaloneReactionAnimation(messageId: item.message.id, standaloneReactionAnimation: standaloneReactionAnimation)
strongSelf.chatDisplayNode.addSubnode(standaloneReactionAnimation)
standaloneReactionAnimation.frame = strongSelf.chatDisplayNode.bounds
standaloneReactionAnimation.animateReactionSelection(
context: strongSelf.context,
theme: strongSelf.presentationData.theme,
animationCache: strongSelf.controllerInteraction!.presentationContext.animationCache,
reaction: reactionItem,
avatarPeers: [],
playHaptic: false,
isLarge: false,
targetView: targetView,
addStandaloneReactionAnimation: { standaloneReactionAnimation in
guard let strongSelf = self else {
return
}
strongSelf.chatDisplayNode.messageTransitionNode.addMessageStandaloneReactionAnimation(messageId: item.message.id, standaloneReactionAnimation: standaloneReactionAnimation)
standaloneReactionAnimation.frame = strongSelf.chatDisplayNode.bounds
strongSelf.chatDisplayNode.addSubnode(standaloneReactionAnimation)
},
completion: { [weak standaloneReactionAnimation] in
standaloneReactionAnimation?.removeFromSupernode()
}
)
}
}
})
} else {
strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts(itemNode: itemNode)
if let removedReaction = removedReaction, let targetView = itemNode.targetReactionView(value: removedReaction), shouldDisplayInlineDateReactions(message: message, isPremium: strongSelf.presentationInterfaceState.isPremium, forceInline: false) {
var hideRemovedReaction: Bool = false
if let reactions = mergedMessageReactions(attributes: message.attributes, isTags: message.areReactionsTags(accountPeerId: context.account.peerId)) {
for reaction in reactions.reactions {
if reaction.value == removedReaction {
hideRemovedReaction = reaction.count == 1
break
}
}
}
let standaloneDismissAnimation = StandaloneDismissReactionAnimation()
standaloneDismissAnimation.frame = strongSelf.chatDisplayNode.bounds
strongSelf.chatDisplayNode.addSubnode(standaloneDismissAnimation)
standaloneDismissAnimation.animateReactionDismiss(sourceView: targetView, hideNode: hideRemovedReaction, isIncoming: message.effectivelyIncoming(strongSelf.context.account.peerId), completion: { [weak standaloneDismissAnimation] in
standaloneDismissAnimation?.removeFromSupernode()
})
}
}
let mappedUpdatedReactions = updatedReactions.map { reaction -> UpdateMessageReaction in
switch reaction {
case let .builtin(value):
return .builtin(value)
case let .custom(fileId):
return .custom(fileId: fileId, file: nil)
case .stars:
return .stars
}
}
if !strongSelf.presentationInterfaceState.isPremium && mappedUpdatedReactions.count > strongSelf.context.userLimits.maxReactionsPerMessage {
let _ = (ApplicationSpecificNotice.incrementMultipleReactionsSuggestion(accountManager: strongSelf.context.sharedContext.accountManager)
|> deliverOnMainQueue).startStandalone(next: { [weak self] count in
guard let self else {
return
}
if count < 1 {
let context = self.context
let controller = UndoOverlayController(
presentationData: self.presentationData,
content: .premiumPaywall(title: nil, text: self.presentationData.strings.Chat_Reactions_MultiplePremiumTooltip, customUndoText: nil, timeout: nil, linkAction: nil),
elevatedLayout: false,
action: { [weak self] action in
if case .info = action {
if let self {
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .reactions, forceDark: false, dismissed: nil)
self.push(controller)
}
}
return true
}
)
self.present(controller, in: .current)
}
})
}
let _ = updateMessageReactionsInteractively(account: strongSelf.context.account, messageIds: [message.id], reactions: mappedUpdatedReactions, isLarge: false, storeAsRecentlyUsed: false).startStandalone()
}
#endif
}
})
}, activateMessagePinch: { [weak self] sourceNode in

View File

@ -41,7 +41,7 @@ extension ChatControllerImpl {
let reactionFile: Signal<TelegramMediaFile?, NoError>
switch value {
case .builtin:
case .builtin, .stars:
reactionFile = self.context.engine.stickers.availableReactions()
|> take(1)
|> map { availableReactions -> TelegramMediaFile? in
@ -161,25 +161,21 @@ extension ChatControllerImpl {
self.window?.presentInGlobalOverlay(controller)
})
} else {
var debug = false
#if DEBUG
debug = true
#endif
if self.context.sharedContext.applicationBindings.appBuildType == .internal {
debug = true
}
if debug, case .custom(MessageReaction.starsReactionId) = value {
if case .stars = value {
gesture?.cancel()
cancelParentGestures(view: sourceView)
let _ = (ChatSendStarsScreen.initialData(context: self.context, peerId: message.id.peerId)
|> deliverOnMainQueue).start(next: { [weak self] initialData in
guard let self, let initialData else {
return
}
self.push(ChatSendStarsScreen(context: self.context, initialData: initialData, completion: { [weak self] amount in
guard let self else {
guard let self, amount > 0 else {
return
}
let _ = self.context.engine.messages.sendStarsReaction(id: message.id, count: Int(amount))
let _ = (self.context.engine.stickers.resolveInlineStickers(fileIds: [MessageReaction.starsReactionId])
|> deliverOnMainQueue).start(next: { [weak self] files in
guard let self, let file = files[MessageReaction.starsReactionId] else {
@ -369,7 +365,7 @@ extension ChatControllerImpl {
let reactionFile: TelegramMediaFile?
switch value {
case .builtin:
case .builtin, .stars:
reactionFile = availableReactions?.reactions.first(where: { $0.value == value })?.selectAnimation
case let .custom(fileId):
reactionFile = customEmoji[fileId]

View File

@ -4031,7 +4031,7 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
var reactionItem: ReactionItem?
switch updatedReaction {
case .builtin:
case .builtin, .stars:
if let availableReactions = item.associatedData.availableReactions {
for reaction in availableReactions.reactions {
guard let centerAnimation = reaction.centerAnimation else {

View File

@ -484,6 +484,8 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, Chat
break
case let .custom(fileId):
customFileIds.append(fileId)
case .stars:
break
}
}
@ -510,7 +512,7 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, Chat
let title = savedMessageTags?.tags.first(where: { $0.reaction == reaction })?.title
switch reaction {
case .builtin:
case .builtin, .stars:
if let availableReactions {
inner: for availableReaction in availableReactions.reactions {
if availableReaction.value == reaction {
@ -763,7 +765,7 @@ final class ChatSearchTitleAccessoryPanelNode: ChatTitleAccessoryPanelNode, Chat
let reactionFile: Signal<TelegramMediaFile?, NoError>
switch reaction {
case .builtin:
case .builtin, .stars:
reactionFile = self.context.engine.stickers.availableReactions()
|> take(1)
|> map { availableReactions -> TelegramMediaFile? in