diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 87b6d3462a..901fd837c3 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -2171,6 +2171,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { messageText = item.presentationData.strings.ChatList_UserReacted(value).string case .custom: break + case .stars: + break } break loop } diff --git a/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift b/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift index 1e37b9b72a..61746938e2 100644 --- a/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift +++ b/submodules/Components/ReactionButtonListComponent/Sources/ReactionButtonListComponent.swift @@ -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 diff --git a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift index 259baf3c12..af576c9cd2 100644 --- a/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift +++ b/submodules/Components/ReactionListContextMenuContent/Sources/ReactionListContextMenuContent.swift @@ -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 = "" diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index ea7827e4fd..05c6be0606 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -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?() }) diff --git a/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift b/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift index 5a1a05e815..7c147f45af 100644 --- a/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift @@ -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 } diff --git a/submodules/ContextUI/Sources/ContextControllerPresentationNode.swift b/submodules/ContextUI/Sources/ContextControllerPresentationNode.swift index 5137890b60..01938595e2 100644 --- a/submodules/ContextUI/Sources/ContextControllerPresentationNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerPresentationNode.swift @@ -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) diff --git a/submodules/ContextUI/Sources/ContextSourceContainer.swift b/submodules/ContextUI/Sources/ContextSourceContainer.swift index ee940e2e49..c54999cb68 100644 --- a/submodules/ContextUI/Sources/ContextSourceContainer.swift +++ b/submodules/ContextUI/Sources/ContextSourceContainer.swift @@ -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, 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() } diff --git a/submodules/DrawingUI/Sources/DrawingReactionView.swift b/submodules/DrawingUI/Sources/DrawingReactionView.swift index 34148e1fb8..26cae6e22a 100644 --- a/submodules/DrawingUI/Sources/DrawingReactionView.swift +++ b/submodules/DrawingUI/Sources/DrawingReactionView.swift @@ -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) + } + }) } } diff --git a/submodules/PeerInfoUI/Sources/PeerAllowedReactionListController.swift b/submodules/PeerInfoUI/Sources/PeerAllowedReactionListController.swift index 589e98d9bc..cc328ee989 100644 --- a/submodules/PeerInfoUI/Sources/PeerAllowedReactionListController.swift +++ b/submodules/PeerInfoUI/Sources/PeerAllowedReactionListController.swift @@ -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() } }) } diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index d007db0582..74e1bc2d72 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -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 diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift index 180f7524c9..31f8bad84b 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift @@ -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) diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 11b0f8515c..8f398218f2 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -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: diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index 79acdb0d0a..4b7744a801 100644 --- a/submodules/TelegramApi/Sources/Api10.swift +++ b/submodules/TelegramApi/Sources/Api10.swift @@ -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 - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api11.swift b/submodules/TelegramApi/Sources/Api11.swift index 8845ce3ec6..7eb2f37326 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -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) diff --git a/submodules/TelegramApi/Sources/Api16.swift b/submodules/TelegramApi/Sources/Api16.swift index 85ed7f414c..11ec61be0d 100644 --- a/submodules/TelegramApi/Sources/Api16.swift +++ b/submodules/TelegramApi/Sources/Api16.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api20.swift b/submodules/TelegramApi/Sources/Api20.swift index 2b1d7e1f79..206cb533bb 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -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 - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api21.swift b/submodules/TelegramApi/Sources/Api21.swift index 83924b0d6b..73eedd5544 100644 --- a/submodules/TelegramApi/Sources/Api21.swift +++ b/submodules/TelegramApi/Sources/Api21.swift @@ -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 - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api22.swift b/submodules/TelegramApi/Sources/Api22.swift index 3d6fc54584..a704866611 100644 --- a/submodules/TelegramApi/Sources/Api22.swift +++ b/submodules/TelegramApi/Sources/Api22.swift @@ -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) diff --git a/submodules/TelegramApi/Sources/Api23.swift b/submodules/TelegramApi/Sources/Api23.swift index 0d646cf4e4..25715e88d9 100644 --- a/submodules/TelegramApi/Sources/Api23.swift +++ b/submodules/TelegramApi/Sources/Api23.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api33.swift b/submodules/TelegramApi/Sources/Api33.swift index 508a3b6a35..e368c5f707 100644 --- a/submodules/TelegramApi/Sources/Api33.swift +++ b/submodules/TelegramApi/Sources/Api33.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api36.swift b/submodules/TelegramApi/Sources/Api36.swift index 6c886c3735..f69c2350f3 100644 --- a/submodules/TelegramApi/Sources/Api36.swift +++ b/submodules/TelegramApi/Sources/Api36.swift @@ -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) { + static func exportChatInvite(flags: Int32, peer: Api.InputPeer, expireDate: Int32?, usageLimit: Int32?, title: String?, subscriptionPricing: Api.StarsSubscriptionPricing?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { 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) { + 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) { 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) { + static func setChatAvailableReactions(flags: Int32, peer: Api.InputPeer, availableReactions: Api.ChatReactions, reactionsLimit: Int32?, paidEnabled: Api.Bool?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { 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) { + 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) { 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) { + 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) { 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) { + 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) { + static func getStarsTransactions(flags: Int32, subscriptionId: String?, peer: Api.InputPeer, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { 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() { diff --git a/submodules/TelegramApi/Sources/Api4.swift b/submodules/TelegramApi/Sources/Api4.swift index 09f23bb178..adaf067144 100644 --- a/submodules/TelegramApi/Sources/Api4.swift +++ b/submodules/TelegramApi/Sources/Api4.swift @@ -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 diff --git a/submodules/TelegramApi/Sources/Api6.swift b/submodules/TelegramApi/Sources/Api6.swift index 177e11efde..f5894fb213 100644 --- a/submodules/TelegramApi/Sources/Api6.swift +++ b/submodules/TelegramApi/Sources/Api6.swift @@ -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 diff --git a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift index ce0867744c..d79353be1e 100644 --- a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift +++ b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift @@ -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 diff --git a/submodules/TelegramCore/Sources/Account/AccountManager.swift b/submodules/TelegramCore/Sources/Account/AccountManager.swift index 5ff3b932f1..a362cd626a 100644 --- a/submodules/TelegramCore/Sources/Account/AccountManager.swift +++ b/submodules/TelegramCore/Sources/Account/AccountManager.swift @@ -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) }) diff --git a/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift b/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift index a288585d95..0a3b612cfe 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/ApiGroupOrChannel.swift @@ -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) diff --git a/submodules/TelegramCore/Sources/ApiUtils/CachedChannelParticipants.swift b/submodules/TelegramCore/Sources/ApiUtils/CachedChannelParticipants.swift index 64f93c7ed6..1ad822c3ad 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/CachedChannelParticipants.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/CachedChannelParticipants.swift @@ -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) diff --git a/submodules/TelegramCore/Sources/ApiUtils/ExportedInvitation.swift b/submodules/TelegramCore/Sources/ApiUtils/ExportedInvitation.swift index ace0b15845..163c9d5890 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/ExportedInvitation.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/ExportedInvitation.swift @@ -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 diff --git a/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift b/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift index 52fd6e0f2c..b82d10da0a 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift @@ -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] diff --git a/submodules/TelegramCore/Sources/Settings/ReactionSettings.swift b/submodules/TelegramCore/Sources/Settings/ReactionSettings.swift index 4069435c74..4d15398c11 100644 --- a/submodules/TelegramCore/Sources/Settings/ReactionSettings.swift +++ b/submodules/TelegramCore/Sources/Settings/ReactionSettings.swift @@ -22,6 +22,8 @@ public extension ReactionSettings { } else { return ReactionSettings.default.quickReaction } + case .stars: + return self.quickReaction } } } diff --git a/submodules/TelegramCore/Sources/State/AccountTaskManager.swift b/submodules/TelegramCore/Sources/State/AccountTaskManager.swift index be1cbc0efc..a0f2ee88a9 100644 --- a/submodules/TelegramCore/Sources/State/AccountTaskManager.swift +++ b/submodules/TelegramCore/Sources/State/AccountTaskManager.swift @@ -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()) diff --git a/submodules/TelegramCore/Sources/State/AvailableReactions.swift b/submodules/TelegramCore/Sources/State/AvailableReactions.swift index 7476c2374f..6b86564953 100644 --- a/submodules/TelegramCore/Sources/State/AvailableReactions.swift +++ b/submodules/TelegramCore/Sources/State/AvailableReactions.swift @@ -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 { diff --git a/submodules/TelegramCore/Sources/State/ManagedConsumePersonalMessagesActions.swift b/submodules/TelegramCore/Sources/State/ManagedConsumePersonalMessagesActions.swift index ace5e77447..ba4ec8405c 100644 --- a/submodules/TelegramCore/Sources/State/ManagedConsumePersonalMessagesActions.swift +++ b/submodules/TelegramCore/Sources/State/ManagedConsumePersonalMessagesActions.swift @@ -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? diff --git a/submodules/TelegramCore/Sources/State/ManagedRecentStickers.swift b/submodules/TelegramCore/Sources/State/ManagedRecentStickers.swift index bac8b35cff..8e48ce953d 100644 --- a/submodules/TelegramCore/Sources/State/ManagedRecentStickers.swift +++ b/submodules/TelegramCore/Sources/State/ManagedRecentStickers.swift @@ -411,6 +411,8 @@ func managedRecentReactions(postbox: Postbox, network: Network) -> Signal Signal map { files -> [OrderedItemListEntry] in @@ -442,6 +446,8 @@ func managedRecentReactions(postbox: Postbox, network: Network) -> Signal Signal Signal map { files -> [OrderedItemListEntry] in @@ -493,6 +503,8 @@ func managedTopReactions(postbox: Postbox, network: Network) -> Signal Signal Signal map { files -> [OrderedItemListEntry] in @@ -544,6 +560,8 @@ func managedDefaultTagReactions(postbox: Postbox, network: Network) -> Signal ignoreValues } +public func sendStarsReactionsInteractively(account: Account, messageId: MessageId, count: Int) -> Signal { + 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 { + 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 = 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 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) -> Signal { +private func withTakenReactionsAction(postbox: Postbox, type: PendingMessageActionType, id: MessageId, _ f: @escaping (Transaction, PendingMessageActionsEntry?) -> Signal) -> Signal { return postbox.transaction { transaction -> Signal 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) -> Signal { + return postbox.transaction { transaction -> Signal 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 { return Signal { _ in let helper = Atomic(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 in + let signal = withTakenReactionsAction(postbox: postbox, type: .updateReaction, id: entry.id, { transaction, entry -> Signal 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 { + return Signal { _ in + let helper = Atomic(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 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 { return requestUpdateMessageReaction(postbox: postbox, network: network, stateManager: stateManager, messageId: id) |> `catch` { _ -> Signal 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 { + return requestSendStarsReaction(postbox: postbox, network: network, stateManager: stateManager, messageId: id) + |> `catch` { _ -> Signal 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 in if error.errorDescription == "CHAT_NOT_MODIFIED" { diff --git a/submodules/TelegramCore/Sources/State/Serialization.swift b/submodules/TelegramCore/Sources/State/Serialization.swift index 9bbff0d1df..9ca64a5e9e 100644 --- a/submodules/TelegramCore/Sources/State/Serialization.swift +++ b/submodules/TelegramCore/Sources/State/Serialization.swift @@ -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! { diff --git a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift index 0ec47fcdf3..79f03b8308 100644 --- a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift +++ b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift @@ -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)) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift index e3e2bd689b..7a81baa260 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift @@ -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 } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedGroupData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedGroupData.swift index 2125bc1a59..544760a6b3 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedGroupData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedGroupData.swift @@ -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 } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift index 928ba32a69..a9bde8238d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift @@ -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] diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift index 6758c55120..7a8bc51b02 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift @@ -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") + } +} diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift index 642ac821c3..c8a0ad4f8c 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_RecentMediaItem.swift @@ -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") } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_UpdateMessageReactionsAction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_UpdateMessageReactionsAction.swift index 7a944f58bf..f62f5ebbbd 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_UpdateMessageReactionsAction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_UpdateMessageReactionsAction.swift @@ -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 + } + } +} diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift index 1531576a48..fa18ad9478 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift @@ -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 } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/EngineStoryViewListContext.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/EngineStoryViewListContext.swift index 136993ab0e..523354bb0f 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/EngineStoryViewListContext.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/EngineStoryViewListContext.swift @@ -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), diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift index 0c24717543..b35b4569ae 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/SendAsPeers.swift @@ -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 } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index d9927f1c2e..d70f325895 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -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 { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift index 0bf8b5549c..ee33e92627 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/Stars.swift @@ -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 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 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) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift index 3f7f163421..cf9161b453 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/AddressNames.swift @@ -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 diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift index ca5df1efee..c2922254c1 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/ChannelRecommendation.swift @@ -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 diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/Communities.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/Communities.swift index 96c9eec56f..31312c3b09 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/Communities.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/Communities.swift @@ -280,7 +280,7 @@ func _internal_checkChatFolderLink(account: Account, slug: String) -> Signal Signal 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)) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/InactiveChannels.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InactiveChannels.swift index 3a8881c801..6886e3cd4d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/InactiveChannels.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InactiveChannels.swift @@ -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 } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift index c8c86a29cf..0aa9bc75a1 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/InvitationLinks.swift @@ -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 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 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) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/JoinLink.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/JoinLink.swift index be5f03b5a7..a23e3c443a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/JoinLink.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/JoinLink.swift @@ -106,7 +106,7 @@ func _internal_joinLinkInformation(_ hash: String, account: Account) -> Signal mapToSignal { result -> Signal 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)))) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/SearchPeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/SearchPeers.swift index d73383b721..f6099c2e55 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/SearchPeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/SearchPeers.swift @@ -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 } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 4f09b015a3..86ebba237e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -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 diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift b/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift index 5576aaec06..503ee7bfa4 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Privacy/UpdatedAccountPrivacySettings.swift @@ -180,7 +180,7 @@ func _internal_requestAccountPrivacySettings(account: Account) -> Signal Signal { +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() - #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) } } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift index ea06826e99..a3a42cc62c 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift @@ -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 + } } } } diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 49c5a40cff..7e99014b87 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -8223,6 +8223,8 @@ private func allowedStoryReactions(context: AccountContext) -> Signal<[ReactionI largeApplicationAnimation: nil, isCustom: true )) + case .stars: + break } } diff --git a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift index 28d1151a16..82fbea852e 100644 --- a/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift +++ b/submodules/TelegramUI/Components/PeerAllowedReactionsScreen/Sources/PeerAllowedReactionsScreen.swift @@ -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 @@ -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 diff --git a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ItemListReactionItem.swift b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ItemListReactionItem.swift index d7c97d8c04..d44e1374d5 100644 --- a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ItemListReactionItem.swift +++ b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ItemListReactionItem.swift @@ -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 + } + } + } } diff --git a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/QuickReactionSetupController.swift b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/QuickReactionSetupController.swift index da5694a1f6..fa0225bc2f 100644 --- a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/QuickReactionSetupController.swift +++ b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/QuickReactionSetupController.swift @@ -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() diff --git a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift index 658f8e70b7..fed06dea72 100644 --- a/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift +++ b/submodules/TelegramUI/Components/Settings/QuickReactionSetupController/Sources/ReactionChatPreviewItem.swift @@ -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 + } + } } } } diff --git a/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift b/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift index 7c2d2b3aa8..fa948e4ced 100644 --- a/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift +++ b/submodules/TelegramUI/Components/Stories/PeerListItemComponent/Sources/PeerListItemComponent.swift @@ -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 diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift index a0f38bbe68..cb8c039a8e 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift @@ -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 } } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift index 6e44780115..71a00344a7 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift @@ -2198,6 +2198,8 @@ func allowedStoryReactions(context: AccountContext) -> Signal<[ReactionItem], No largeApplicationAnimation: nil, isCustom: true )) + case .stars: + break } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift index 283d05ac45..6ce4ea56fc 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemOverlaysView.swift @@ -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 + } + } + } } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift index 1da76de05d..26b19cb9a1 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerComponent.swift @@ -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() diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift index e7a36f29ae..bb57628710 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift @@ -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 + } + } + } } } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift index 29ea4a4726..843fe4d68b 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetViewListComponent.swift @@ -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, diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index 37815b55ac..6e98ac5a67 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift index 159982e4a9..49797c3aac 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenMessageContextMenu.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/Chat/PeerMessageSelectedReactions.swift b/submodules/TelegramUI/Sources/Chat/PeerMessageSelectedReactions.swift index 138e33de1c..0d41a830af 100644 --- a/submodules/TelegramUI/Sources/Chat/PeerMessageSelectedReactions.swift +++ b/submodules/TelegramUI/Sources/Chat/PeerMessageSelectedReactions.swift @@ -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) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 30c8cab465..ee2d82c7b3 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift b/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift index 4f54e76bcf..16ba4e04a4 100644 --- a/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift +++ b/submodules/TelegramUI/Sources/ChatControllerOpenMessageReactionContextMenu.swift @@ -41,7 +41,7 @@ extension ChatControllerImpl { let reactionFile: Signal 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] diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index 7d9993a2f2..c750ad853a 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -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 { diff --git a/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift index 1dbeb89377..fae6aca654 100644 --- a/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchTitleAccessoryPanelNode.swift @@ -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 switch reaction { - case .builtin: + case .builtin, .stars: reactionFile = self.context.engine.stickers.availableReactions() |> take(1) |> map { availableReactions -> TelegramMediaFile? in