mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Merge branch 'master' into story-folders
# Conflicts: # submodules/TelegramCore/Sources/TelegramEngine/Payments/StarGifts.swift
This commit is contained in:
commit
1df896f59a
@ -14686,3 +14686,7 @@ Sorry for the inconvenience.";
|
||||
"Gift.Unique.CollectibleBy" = "collectible %1$@ by %2$@";
|
||||
|
||||
"SendInviteLink.TextCallsRestrictedSendOneInviteLink" = "**%@** restricts calling them. You can send them an invite link to call instead.";
|
||||
|
||||
"Chat.ReplyPanel.ReplyToTodoItem" = "Reply to Checklist Item";
|
||||
|
||||
"Chat.Todo.ReplyToItem" = "Reply to Item";
|
||||
|
||||
@ -44,6 +44,7 @@ public enum PremiumIntroSource {
|
||||
case messageEffects
|
||||
case todo
|
||||
case auth(String)
|
||||
case premiumGift(TelegramMediaFile)
|
||||
}
|
||||
|
||||
public enum PremiumGiftSource: Equatable {
|
||||
|
||||
@ -941,7 +941,7 @@ final class AttachmentPanel: ASDisplayNode, ASScrollViewDelegate {
|
||||
self.mainButtonNode.addTarget(self, action: #selector(self.mainButtonPressed), forControlEvents: .touchUpInside)
|
||||
self.secondaryButtonNode.addTarget(self, action: #selector(self.secondaryButtonPressed), forControlEvents: .touchUpInside)
|
||||
|
||||
self.interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
|
||||
self.interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _, _ in
|
||||
}, setupEditMessage: { _, _ in
|
||||
}, beginMessageSelection: { _, _ in
|
||||
}, cancelMessageSelection: { _ in
|
||||
|
||||
@ -481,16 +481,19 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
public struct ReplyMessageSubject: Codable, Equatable {
|
||||
public var messageId: EngineMessage.Id
|
||||
public var quote: EngineMessageReplyQuote?
|
||||
public var todoItemId: Int32?
|
||||
|
||||
public init(messageId: EngineMessage.Id, quote: EngineMessageReplyQuote?) {
|
||||
public init(messageId: EngineMessage.Id, quote: EngineMessageReplyQuote?, todoItemId: Int32?) {
|
||||
self.messageId = messageId
|
||||
self.quote = quote
|
||||
self.todoItemId = todoItemId
|
||||
}
|
||||
|
||||
public var subjectModel: EngineMessageReplySubject {
|
||||
return EngineMessageReplySubject(
|
||||
messageId: self.messageId,
|
||||
quote: self.quote
|
||||
quote: self.quote,
|
||||
todoItemId: self.todoItemId
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -545,7 +548,8 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
var result = self.withUpdatedComposeInputState(ChatTextInputState(inputText: chatInputStateStringWithAppliedEntities(state?.text ?? "", entities: state?.entities ?? []))).withUpdatedReplyMessageSubject((state?.replySubject).flatMap {
|
||||
return ReplyMessageSubject(
|
||||
messageId: $0.messageId,
|
||||
quote: $0.quote
|
||||
quote: $0.quote,
|
||||
todoItemId: $0.todoItemId
|
||||
)
|
||||
})
|
||||
if let timestamp = state?.timestamp {
|
||||
@ -629,7 +633,7 @@ public final class ChatInterfaceState: Codable, Equatable {
|
||||
let replyMessageIdNamespace: Int32? = try? container.decodeIfPresent(Int32.self, forKey: "r.n")
|
||||
let replyMessageIdId: Int32? = try? container.decodeIfPresent(Int32.self, forKey: "r.i")
|
||||
if let replyMessageIdPeerId = replyMessageIdPeerId, let replyMessageIdNamespace = replyMessageIdNamespace, let replyMessageIdId = replyMessageIdId {
|
||||
self.replyMessageSubject = ReplyMessageSubject(messageId: EngineMessage.Id(peerId: EnginePeer.Id(replyMessageIdPeerId), namespace: replyMessageIdNamespace, id: replyMessageIdId), quote: nil)
|
||||
self.replyMessageSubject = ReplyMessageSubject(messageId: EngineMessage.Id(peerId: EnginePeer.Id(replyMessageIdPeerId), namespace: replyMessageIdNamespace, id: replyMessageIdId), quote: nil, todoItemId: nil)
|
||||
} else {
|
||||
self.replyMessageSubject = nil
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ public final class ChatPanelInterfaceInteraction {
|
||||
case editPrice
|
||||
}
|
||||
|
||||
public let setupReplyMessage: (MessageId?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void
|
||||
public let setupReplyMessage: (MessageId?, Int32?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void
|
||||
public let setupEditMessage: (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void
|
||||
public let beginMessageSelection: ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void
|
||||
public let cancelMessageSelection: (ContainedViewLayoutTransition) -> Void
|
||||
@ -192,7 +192,7 @@ public final class ChatPanelInterfaceInteraction {
|
||||
public let statuses: ChatPanelInterfaceInteractionStatuses?
|
||||
|
||||
public init(
|
||||
setupReplyMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void,
|
||||
setupReplyMessage: @escaping (MessageId?, Int32?, @escaping (ContainedViewLayoutTransition, @escaping () -> Void) -> Void) -> Void,
|
||||
setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
|
||||
beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void,
|
||||
cancelMessageSelection: @escaping (ContainedViewLayoutTransition) -> Void,
|
||||
@ -443,7 +443,7 @@ public final class ChatPanelInterfaceInteraction {
|
||||
updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void,
|
||||
openLinkEditing: @escaping () -> Void
|
||||
) {
|
||||
self.init(setupReplyMessage: { _, _ in
|
||||
self.init(setupReplyMessage: { _, _, _ in
|
||||
}, setupEditMessage: { _, _ in
|
||||
}, beginMessageSelection: { _, _ in
|
||||
}, cancelMessageSelection: { _ in
|
||||
|
||||
@ -1059,6 +1059,34 @@ public struct ComponentTransition {
|
||||
}
|
||||
}
|
||||
|
||||
public func setShapeLayerStrokeColor(layer: CAShapeLayer, color: UIColor, completion: ((Bool) -> Void)? = nil) {
|
||||
if let current = layer.strokeColor, current == color.cgColor {
|
||||
completion?(true)
|
||||
return
|
||||
}
|
||||
|
||||
switch self.animation {
|
||||
case .none:
|
||||
layer.strokeColor = color.cgColor
|
||||
completion?(true)
|
||||
case let .curve(duration, curve):
|
||||
let previousColor: CGColor = layer.strokeColor ?? UIColor.clear.cgColor
|
||||
layer.strokeColor = color.cgColor
|
||||
|
||||
layer.animate(
|
||||
from: previousColor,
|
||||
to: color.cgColor,
|
||||
keyPath: "strokeColor",
|
||||
duration: duration,
|
||||
delay: 0.0,
|
||||
curve: curve,
|
||||
removeOnCompletion: true,
|
||||
additive: false,
|
||||
completion: completion
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public func setShapeLayerStrokeStart(layer: CAShapeLayer, strokeStart: CGFloat, completion: ((Bool) -> Void)? = nil) {
|
||||
switch self.animation {
|
||||
case .none:
|
||||
|
||||
@ -288,7 +288,7 @@ final class ComposePollScreenComponent: Component {
|
||||
self.reorderingItem = nil
|
||||
for (itemId, itemView) in self.pollOptionsSectionContainer.itemViews {
|
||||
if itemId == reorderingItem.id, let view = itemView.contents.view {
|
||||
let viewFrame = view.convert(view.bounds, to: self)
|
||||
let viewFrame = view.convert(view.bounds, to: self.scrollView)
|
||||
let transition = ComponentTransition.spring(duration: 0.3)
|
||||
transition.setPosition(view: reorderingItem.snapshotView, position: viewFrame.center)
|
||||
transition.setAlpha(view: reorderingItem.backgroundView, alpha: 0.0, completion: { _ in
|
||||
@ -311,13 +311,14 @@ final class ComposePollScreenComponent: Component {
|
||||
|
||||
snapshotView.center = targetPosition
|
||||
|
||||
let localPoint = self.pollOptionsSectionContainer.convert(targetPosition, from: self.scrollView)
|
||||
for (itemId, itemView) in self.pollOptionsSectionContainer.itemViews {
|
||||
if itemId == id {
|
||||
continue
|
||||
}
|
||||
if let view = itemView.contents.view {
|
||||
let viewFrame = view.convert(view.bounds, to: self)
|
||||
if viewFrame.contains(targetPosition) {
|
||||
let viewFrame = view.convert(view.bounds, to: self.pollOptionsSectionContainer)
|
||||
if viewFrame.contains(localPoint) {
|
||||
if let targetIndex = self.pollOptions.firstIndex(where: { AnyHashable($0.id) == itemId }), let reorderingItem = self.pollOptions.first(where: { AnyHashable($0.id) == id }) {
|
||||
self.reorderIfPossible(item: reorderingItem, toIndex: targetIndex)
|
||||
}
|
||||
|
||||
@ -1346,86 +1346,6 @@ private final class StickerVideoDecoration: UniversalVideoDecoration {
|
||||
}
|
||||
}
|
||||
|
||||
private extension UIBezierPath {
|
||||
static func smoothCurve(
|
||||
through points: [CGPoint],
|
||||
length: CGFloat
|
||||
) -> UIBezierPath {
|
||||
let angle = (CGFloat.pi * 2) / CGFloat(points.count)
|
||||
let smoothness: CGFloat = ((4 / 3) * tan(angle / 4)) / sin(angle / 2) / 2
|
||||
|
||||
var smoothPoints = [SmoothPoint]()
|
||||
for index in (0 ..< points.count) {
|
||||
let prevIndex = index - 1
|
||||
let prev = points[prevIndex >= 0 ? prevIndex : points.count + prevIndex]
|
||||
let curr = points[index]
|
||||
let next = points[(index + 1) % points.count]
|
||||
|
||||
let angle: CGFloat = {
|
||||
let dx = next.x - prev.x
|
||||
let dy = -next.y + prev.y
|
||||
let angle = atan2(dy, dx)
|
||||
if angle < 0 {
|
||||
return abs(angle)
|
||||
} else {
|
||||
return 2 * .pi - angle
|
||||
}
|
||||
}()
|
||||
|
||||
smoothPoints.append(
|
||||
SmoothPoint(
|
||||
point: curr,
|
||||
inAngle: angle + .pi,
|
||||
inLength: smoothness * distance(from: curr, to: prev),
|
||||
outAngle: angle,
|
||||
outLength: smoothness * distance(from: curr, to: next)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
let resultPath = UIBezierPath()
|
||||
resultPath.move(to: smoothPoints[0].point)
|
||||
for index in (0 ..< smoothPoints.count) {
|
||||
let curr = smoothPoints[index]
|
||||
let next = smoothPoints[(index + 1) % points.count]
|
||||
let currSmoothOut = curr.smoothOut()
|
||||
let nextSmoothIn = next.smoothIn()
|
||||
resultPath.addCurve(to: next.point, controlPoint1: currSmoothOut, controlPoint2: nextSmoothIn)
|
||||
}
|
||||
resultPath.close()
|
||||
return resultPath
|
||||
}
|
||||
|
||||
static private func distance(from fromPoint: CGPoint, to toPoint: CGPoint) -> CGFloat {
|
||||
return sqrt((fromPoint.x - toPoint.x) * (fromPoint.x - toPoint.x) + (fromPoint.y - toPoint.y) * (fromPoint.y - toPoint.y))
|
||||
}
|
||||
|
||||
struct SmoothPoint {
|
||||
let point: CGPoint
|
||||
|
||||
let inAngle: CGFloat
|
||||
let inLength: CGFloat
|
||||
|
||||
let outAngle: CGFloat
|
||||
let outLength: CGFloat
|
||||
|
||||
func smoothIn() -> CGPoint {
|
||||
return smooth(angle: inAngle, length: inLength)
|
||||
}
|
||||
|
||||
func smoothOut() -> CGPoint {
|
||||
return smooth(angle: outAngle, length: outLength)
|
||||
}
|
||||
|
||||
private func smooth(angle: CGFloat, length: CGFloat) -> CGPoint {
|
||||
return CGPoint(
|
||||
x: point.x + length * cos(angle),
|
||||
y: point.y + length * sin(angle)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UIImageView {
|
||||
func setDrawingAnimatedImage(data: Data) {
|
||||
DispatchQueue.global().async {
|
||||
|
||||
@ -60,7 +60,8 @@ swift_library(
|
||||
"//submodules/TelegramUI/Components/AnimatedTextComponent",
|
||||
"//submodules/TelegramUI/Components/LottieComponent",
|
||||
"//submodules/Components/MultilineTextComponent",
|
||||
"//submodules/Components/BundleIconComponent",
|
||||
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
||||
"//submodules/Components/BundleIconComponent",
|
||||
"//submodules/Components/BalancedTextComponent",
|
||||
"//submodules/Components/ComponentDisplayAdapters",
|
||||
"//submodules/ComponentFlow",
|
||||
|
||||
@ -4,6 +4,7 @@ import Display
|
||||
import SwiftSignalKit
|
||||
import ComponentFlow
|
||||
import MultilineTextComponent
|
||||
import MultilineTextWithEntitiesComponent
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
@ -12,6 +13,7 @@ import PlainButtonComponent
|
||||
import AvatarNode
|
||||
import AccountContext
|
||||
import PhotoResources
|
||||
import TextFormat
|
||||
|
||||
final class VideoAdComponent: Component {
|
||||
let context: AccountContext
|
||||
@ -138,12 +140,23 @@ final class VideoAdComponent: Component {
|
||||
environment: {},
|
||||
containerSize: CGSize(width: availableSize.width - leftInset - rightInset, height: availableSize.height)
|
||||
)
|
||||
|
||||
let textColor = UIColor.white
|
||||
|
||||
var entities: [MessageTextEntity] = []
|
||||
if let attribute = component.message.attributes.first(where: { $0 is TextEntitiesMessageAttribute }) as? TextEntitiesMessageAttribute {
|
||||
entities = attribute.entities
|
||||
}
|
||||
let attributedText = stringWithAppliedEntities(component.message.text, entities: entities, baseColor: textColor, linkColor: textColor, baseFont: Font.regular(14.0), linkFont: Font.regular(14.0), boldFont: Font.semibold(14.0), italicFont: Font.italic(14.0), boldItalicFont: Font.semiboldItalic(14.0), fixedFont: Font.monospace(14.0), blockQuoteFont: Font.regular(14.0), message: nil)
|
||||
let textSize = self.text.update(
|
||||
transition: .immediate,
|
||||
component: AnyComponent(
|
||||
MultilineTextComponent(
|
||||
text: .plain(NSAttributedString(string: component.message.text, font: Font.regular(14.0), textColor: .white)),
|
||||
maximumNumberOfLines: 0
|
||||
MultilineTextWithEntitiesComponent(
|
||||
context: component.context,
|
||||
animationCache: component.context.animationCache,
|
||||
animationRenderer: component.context.animationRenderer,
|
||||
placeholderColor: UIColor.white.withAlphaComponent(0.2),
|
||||
text: .plain(attributedText)
|
||||
)
|
||||
),
|
||||
environment: {},
|
||||
|
||||
@ -20,6 +20,7 @@ class EmojiHeaderComponent: Component {
|
||||
let placeholderColor: UIColor
|
||||
let accentColor: UIColor
|
||||
let fileId: Int64
|
||||
let file: TelegramMediaFile?
|
||||
let isVisible: Bool
|
||||
let hasIdleAnimations: Bool
|
||||
|
||||
@ -30,6 +31,7 @@ class EmojiHeaderComponent: Component {
|
||||
placeholderColor: UIColor,
|
||||
accentColor: UIColor,
|
||||
fileId: Int64,
|
||||
file: TelegramMediaFile? = nil,
|
||||
isVisible: Bool,
|
||||
hasIdleAnimations: Bool
|
||||
) {
|
||||
@ -39,6 +41,7 @@ class EmojiHeaderComponent: Component {
|
||||
self.placeholderColor = placeholderColor
|
||||
self.accentColor = accentColor
|
||||
self.fileId = fileId
|
||||
self.file = file
|
||||
self.isVisible = isVisible
|
||||
self.hasIdleAnimations = hasIdleAnimations
|
||||
}
|
||||
@ -156,7 +159,7 @@ class EmojiHeaderComponent: Component {
|
||||
animationCache: component.animationCache,
|
||||
animationRenderer: component.animationRenderer,
|
||||
content: .animation(
|
||||
content: .customEmoji(fileId: component.fileId),
|
||||
content: component.file.flatMap { .file(file: $0) } ?? .customEmoji(fileId: component.fileId),
|
||||
size: CGSize(width: 100.0, height: 100.0),
|
||||
placeholderColor: component.placeholderColor,
|
||||
themeColor: component.accentColor,
|
||||
@ -170,6 +173,10 @@ class EmojiHeaderComponent: Component {
|
||||
)
|
||||
self.statusView.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - size.width) / 2.0), y: 63.0), size: size)
|
||||
|
||||
if let _ = component.file {
|
||||
self.statusView.isHidden = false
|
||||
}
|
||||
|
||||
return availableSize
|
||||
}
|
||||
}
|
||||
|
||||
@ -315,6 +315,12 @@ public enum PremiumSource: Equatable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .premiumGift(lhsFile):
|
||||
if case let .premiumGift(rhsFile) = rhs, lhsFile.id == rhsFile.id {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -364,6 +370,7 @@ public enum PremiumSource: Equatable {
|
||||
case messageEffects
|
||||
case todo
|
||||
case auth(String)
|
||||
case premiumGift(TelegramMediaFile)
|
||||
|
||||
var identifier: String? {
|
||||
switch self {
|
||||
@ -461,6 +468,8 @@ public enum PremiumSource: Equatable {
|
||||
return "todo"
|
||||
case .auth:
|
||||
return "auth"
|
||||
case .premiumGift:
|
||||
return "premium_gift"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1817,7 +1826,10 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent {
|
||||
|
||||
var link = ""
|
||||
let textString: String
|
||||
if case .emojiStatus = context.component.source {
|
||||
if case .premiumGift = context.component.source {
|
||||
//TODO:localize
|
||||
textString = "Subscribe to **Telegram Premium** to send up to **5** of these gifts and unlock access to multiple additional features."
|
||||
} else if case .emojiStatus = context.component.source {
|
||||
textString = strings.Premium_EmojiStatusText.replacingOccurrences(of: "#", with: "# ")
|
||||
} else if case .giftTerms = context.component.source {
|
||||
textString = strings.Premium_PersonalDescription
|
||||
@ -3354,6 +3366,22 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
||||
availableSize: CGSize(width: min(414.0, context.availableSize.width), height: 220.0),
|
||||
transition: context.transition
|
||||
)
|
||||
} else if case let .premiumGift(file) = context.component.source, case let .accountContext(accountContext) = context.component.screenContext {
|
||||
header = emoji.update(
|
||||
component: EmojiHeaderComponent(
|
||||
context: accountContext,
|
||||
animationCache: accountContext.animationCache,
|
||||
animationRenderer: accountContext.animationRenderer,
|
||||
placeholderColor: environment.theme.list.mediaPlaceholderColor,
|
||||
accentColor: environment.theme.list.itemAccentColor,
|
||||
fileId: file.fileId.id,
|
||||
file: file,
|
||||
isVisible: starIsVisible,
|
||||
hasIdleAnimations: state.hasIdleAnimations
|
||||
),
|
||||
availableSize: CGSize(width: min(414.0, context.availableSize.width), height: 220.0),
|
||||
transition: context.transition
|
||||
)
|
||||
} else {
|
||||
header = star.update(
|
||||
component: PremiumStarComponent(
|
||||
@ -3389,7 +3417,10 @@ private final class PremiumIntroScreenComponent: CombinedComponent {
|
||||
)
|
||||
|
||||
let titleString: String
|
||||
if case .business = context.component.mode {
|
||||
if case .premiumGift = context.component.source {
|
||||
//TODO:localize
|
||||
titleString = "Premium Gift"
|
||||
} else if case .business = context.component.mode {
|
||||
titleString = environment.strings.Business_Title
|
||||
} else if case .emojiStatus = context.component.source {
|
||||
titleString = environment.strings.Premium_Title
|
||||
|
||||
@ -43,41 +43,6 @@ private func parseAuthTransferUrl(_ url: URL) -> Data? {
|
||||
return nil
|
||||
}
|
||||
|
||||
private func generateFrameImage() -> UIImage? {
|
||||
return generateImage(CGSize(width: 64.0, height: 64.0), contextGenerator: { size, context in
|
||||
let bounds = CGRect(origin: CGPoint(), size: size)
|
||||
context.clear(bounds)
|
||||
context.setStrokeColor(UIColor.white.cgColor)
|
||||
context.setLineWidth(4.0)
|
||||
context.setLineCap(.round)
|
||||
|
||||
let path = CGMutablePath()
|
||||
path.move(to: CGPoint(x: 2.0, y: 2.0 + 26.0))
|
||||
path.addArc(tangent1End: CGPoint(x: 2.0, y: 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: 2.0), radius: 6.0)
|
||||
path.addLine(to: CGPoint(x: 2.0 + 26.0, y: 2.0))
|
||||
context.addPath(path)
|
||||
context.strokePath()
|
||||
|
||||
path.move(to: CGPoint(x: size.width - 2.0, y: 2.0 + 26.0))
|
||||
path.addArc(tangent1End: CGPoint(x: size.width - 2.0, y: 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: 2.0), radius: 6.0)
|
||||
path.addLine(to: CGPoint(x: size.width - 2.0 - 26.0, y: 2.0))
|
||||
context.addPath(path)
|
||||
context.strokePath()
|
||||
|
||||
path.move(to: CGPoint(x: 2.0, y: size.height - 2.0 - 26.0))
|
||||
path.addArc(tangent1End: CGPoint(x: 2.0, y: size.height - 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: size.height - 2.0), radius: 6.0)
|
||||
path.addLine(to: CGPoint(x: 2.0 + 26.0, y: size.height - 2.0))
|
||||
context.addPath(path)
|
||||
context.strokePath()
|
||||
|
||||
path.move(to: CGPoint(x: size.width - 2.0, y: size.height - 2.0 - 26.0))
|
||||
path.addArc(tangent1End: CGPoint(x: size.width - 2.0, y: size.height - 2.0), tangent2End: CGPoint(x: 2.0 + 26.0, y: size.height - 2.0), radius: 6.0)
|
||||
path.addLine(to: CGPoint(x: size.width - 2.0 - 26.0, y: size.height - 2.0))
|
||||
context.addPath(path)
|
||||
context.strokePath()
|
||||
})?.stretchableImage(withLeftCapWidth: 32, topCapHeight: 32)
|
||||
}
|
||||
|
||||
public final class QrCodeScanScreen: ViewController {
|
||||
public enum Subject {
|
||||
case authTransfer(activeSessionsContext: ActiveSessionsContext)
|
||||
|
||||
@ -172,7 +172,7 @@ private final class BubbleSettingsControllerNode: ASDisplayNode, ASScrollViewDel
|
||||
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false))
|
||||
|
||||
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false))
|
||||
|
||||
let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA="
|
||||
|
||||
@ -450,7 +450,7 @@ private final class TextSizeSelectionControllerNode: ASDisplayNode, ASScrollView
|
||||
let message1 = Message(stableId: 4, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 4), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66003, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message1], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false))
|
||||
|
||||
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message2 = Message(stableId: 3, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 3), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66002, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(self.context.sharedContext.makeChatMessagePreviewItem(context: self.context, messages: [message2], theme: self.presentationData.theme, strings: self.presentationData.strings, wallpaper: self.presentationData.chatWallpaper, fontSize: self.presentationData.chatFontSize, chatBubbleCorners: self.presentationData.chatBubbleCorners, dateTimeFormat: self.presentationData.dateTimeFormat, nameOrder: self.presentationData.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: self.chatBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false))
|
||||
|
||||
let waveformBase64 = "DAAOAAkACQAGAAwADwAMABAADQAPABsAGAALAA0AGAAfABoAHgATABgAGQAYABQADAAVABEAHwANAA0ACQAWABkACQAOAAwACQAfAAAAGQAVAAAAEwATAAAACAAfAAAAHAAAABwAHwAAABcAGQAAABQADgAAABQAHwAAAB8AHwAAAAwADwAAAB8AEwAAABoAFwAAAB8AFAAAAAAAHwAAAAAAHgAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAHwAAAAAAAAA="
|
||||
|
||||
@ -614,7 +614,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
messages[message4.id] = message4
|
||||
sampleMessages.append(message4)
|
||||
|
||||
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
messages[message5.id] = message5
|
||||
sampleMessages.append(message5)
|
||||
|
||||
@ -625,7 +625,7 @@ final class ThemePreviewControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
sampleMessages.append(message6)
|
||||
|
||||
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
sampleMessages.append(message7)
|
||||
|
||||
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
|
||||
@ -167,7 +167,7 @@ class ThemeSettingsChatPreviewItemNode: ListViewItemNode {
|
||||
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: text, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
}
|
||||
|
||||
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: messageItem.outgoing ? otherPeerId : peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageItem.outgoing ? TelegramUser(id: otherPeerId, accessHash: nil, firstName: "", lastName: "", username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [], emojiStatus: nil, usernames: [], storiesHidden: nil, nameColor: nil, backgroundEmojiId: nil, profileColor: nil, profileBackgroundEmojiId: nil, subscriberCount: nil, verificationIconFileId: nil) : nil, text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)] : [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false))
|
||||
}
|
||||
|
||||
|
||||
@ -1997,10 +1997,10 @@ public final class ShareController: ViewController {
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: url + "\n\n" + text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap {
|
||||
EngineMessageReplySubject(messageId: $0, quote: nil)
|
||||
EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil)
|
||||
}, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
} else {
|
||||
messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: url, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently, sendPaidMessageStars: requiresStars[peerId])
|
||||
shareSignals.append(enqueueMessages(account: currentContext.context.account, peerId: peerId, messages: messages))
|
||||
@ -2033,9 +2033,9 @@ public final class ShareController: ViewController {
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: string, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently, sendPaidMessageStars: requiresStars[peerId])
|
||||
shareSignals.append(enqueueMessages(account: currentContext.context.account, peerId: peerId, messages: messages))
|
||||
}
|
||||
@ -2067,12 +2067,12 @@ public final class ShareController: ViewController {
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
let attributedText = NSMutableAttributedString(string: string, attributes: [ChatTextInputAttributes.italic: true as NSNumber])
|
||||
attributedText.append(NSAttributedString(string: "\n\n\(url)"))
|
||||
let entities = generateChatInputTextEntities(attributedText)
|
||||
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: attributedText.string, attributes: [TextEntitiesMessageAttribute(entities: entities)], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently, sendPaidMessageStars: requiresStars[peerId])
|
||||
shareSignals.append(enqueueMessages(account: currentContext.context.account, peerId: peerId, messages: messages))
|
||||
}
|
||||
@ -2103,7 +2103,7 @@ public final class ShareController: ViewController {
|
||||
}
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: .standalone(media: TelegramMediaImage(imageId: MediaId(namespace: Namespaces.Media.LocalImage, id: Int64.random(in: Int64.min ... Int64.max)), representations: representations.map({ $0.representation }), immediateThumbnailData: nil, reference: nil, partialReference: nil, flags: [])), threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently, sendPaidMessageStars: requiresStars[peerId])
|
||||
shareSignals.append(enqueueMessages(account: currentContext.context.account, peerId: peerId, messages: messages))
|
||||
}
|
||||
@ -2187,7 +2187,7 @@ public final class ShareController: ViewController {
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty && !sendTextAsCaption {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
var attributes: [MessageAttribute] = []
|
||||
if let startAtTimestamp = mediaParameters?.startAtTimestamp, let startAtTimestampNode = strongSelf.controllerNode.startAtTimestampNode, startAtTimestampNode.value {
|
||||
@ -2196,7 +2196,7 @@ public final class ShareController: ViewController {
|
||||
if let forwardSourceMessageId {
|
||||
messages.append(.forward(source: forwardSourceMessageId, threadId: threadId, grouping: .auto, attributes: attributes, correlationId: nil))
|
||||
} else {
|
||||
messages.append(.message(text: sendTextAsCaption ? text : "", attributes: attributes, inlineStickers: [:], mediaReference: mediaReference, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: sendTextAsCaption ? text : "", attributes: attributes, inlineStickers: [:], mediaReference: mediaReference, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently, sendPaidMessageStars: requiresStars[peerId])
|
||||
shareSignals.append(enqueueMessages(account: currentContext.context.account, peerId: peerId, messages: messages))
|
||||
@ -2229,9 +2229,9 @@ public final class ShareController: ViewController {
|
||||
|
||||
var messages: [EnqueueMessage] = []
|
||||
if !text.isEmpty {
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
|
||||
messages = transformMessages(messages, showNames: showNames, silently: silently, sendPaidMessageStars: requiresStars[peerId])
|
||||
shareSignals.append(enqueueMessages(account: currentContext.context.account, peerId: peerId, messages: messages))
|
||||
}
|
||||
@ -2265,7 +2265,7 @@ public final class ShareController: ViewController {
|
||||
|
||||
let correlationId = Int64.random(in: Int64.min ... Int64.max)
|
||||
correlationIds.append(correlationId)
|
||||
messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []))
|
||||
messagesToEnqueue.append(.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: threadId, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: correlationId, bubbleUpEmojiOrStickersets: []))
|
||||
}
|
||||
for message in messages {
|
||||
for media in message.media {
|
||||
|
||||
@ -953,6 +953,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[520210263] = { return Api.StarGiftAttributeId.parse_starGiftAttributeIdBackdrop($0) }
|
||||
dict[1219145276] = { return Api.StarGiftAttributeId.parse_starGiftAttributeIdModel($0) }
|
||||
dict[1242965043] = { return Api.StarGiftAttributeId.parse_starGiftAttributeIdPattern($0) }
|
||||
dict[-1653926992] = { return Api.StarGiftCollection.parse_starGiftCollection($0) }
|
||||
dict[-586389774] = { return Api.StarRefProgram.parse_starRefProgram($0) }
|
||||
dict[-1145654109] = { return Api.StarsAmount.parse_starsAmount($0) }
|
||||
dict[1957618656] = { return Api.StarsAmount.parse_starsTonAmount($0) }
|
||||
@ -1431,6 +1432,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[-1803939105] = { return Api.payments.ResaleStarGifts.parse_resaleStarGifts($0) }
|
||||
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }
|
||||
dict[-1779201615] = { return Api.payments.SavedStarGifts.parse_savedStarGifts($0) }
|
||||
dict[-1977011469] = { return Api.payments.StarGiftCollections.parse_starGiftCollections($0) }
|
||||
dict[-1598402793] = { return Api.payments.StarGiftCollections.parse_starGiftCollectionsNotModified($0) }
|
||||
dict[377215243] = { return Api.payments.StarGiftUpgradePreview.parse_starGiftUpgradePreview($0) }
|
||||
dict[-2069218660] = { return Api.payments.StarGiftWithdrawalUrl.parse_starGiftWithdrawalUrl($0) }
|
||||
dict[785918357] = { return Api.payments.StarGifts.parse_starGifts($0) }
|
||||
@ -2141,6 +2144,8 @@ public extension Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.StarGiftAttributeId:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.StarGiftCollection:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.StarRefProgram:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.StarsAmount:
|
||||
@ -2545,6 +2550,8 @@ public extension Api {
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.payments.SavedStarGifts:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.payments.StarGiftCollections:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.payments.StarGiftUpgradePreview:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.payments.StarGiftWithdrawalUrl:
|
||||
|
||||
@ -1,3 +1,61 @@
|
||||
public extension Api {
|
||||
enum StarGiftCollection: TypeConstructorDescription {
|
||||
case starGiftCollection(flags: Int32, collectionId: Int32, title: String, icon: Api.Document?, giftsCount: Int32, hash: Int64)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .starGiftCollection(let flags, let collectionId, let title, let icon, let giftsCount, let hash):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1653926992)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(collectionId, buffer: buffer, boxed: false)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {icon!.serialize(buffer, true)}
|
||||
serializeInt32(giftsCount, buffer: buffer, boxed: false)
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .starGiftCollection(let flags, let collectionId, let title, let icon, let giftsCount, let hash):
|
||||
return ("starGiftCollection", [("flags", flags as Any), ("collectionId", collectionId as Any), ("title", title as Any), ("icon", icon as Any), ("giftsCount", giftsCount as Any), ("hash", hash as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_starGiftCollection(_ reader: BufferReader) -> StarGiftCollection? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: String?
|
||||
_3 = parseString(reader)
|
||||
var _4: Api.Document?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.Document
|
||||
} }
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: Int64?
|
||||
_6 = reader.readInt64()
|
||||
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.StarGiftCollection.starGiftCollection(flags: _1!, collectionId: _2!, title: _3!, icon: _4, giftsCount: _5!, hash: _6!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum StarRefProgram: TypeConstructorDescription {
|
||||
case starRefProgram(flags: Int32, botId: Int64, commissionPermille: Int32, durationMonths: Int32?, endDate: Int32?, dailyRevenuePerUser: Api.StarsAmount?)
|
||||
@ -1242,49 +1300,3 @@ public extension Api {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum StickerPack: TypeConstructorDescription {
|
||||
case stickerPack(emoticon: String, documents: [Int64])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .stickerPack(let emoticon, let documents):
|
||||
if boxed {
|
||||
buffer.appendInt32(313694676)
|
||||
}
|
||||
serializeString(emoticon, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(documents.count))
|
||||
for item in documents {
|
||||
serializeInt64(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .stickerPack(let emoticon, let documents):
|
||||
return ("stickerPack", [("emoticon", emoticon as Any), ("documents", documents as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_stickerPack(_ reader: BufferReader) -> StickerPack? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: [Int64]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.StickerPack.stickerPack(emoticon: _1!, documents: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,49 @@
|
||||
public extension Api {
|
||||
enum StickerPack: TypeConstructorDescription {
|
||||
case stickerPack(emoticon: String, documents: [Int64])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .stickerPack(let emoticon, let documents):
|
||||
if boxed {
|
||||
buffer.appendInt32(313694676)
|
||||
}
|
||||
serializeString(emoticon, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(documents.count))
|
||||
for item in documents {
|
||||
serializeInt64(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .stickerPack(let emoticon, let documents):
|
||||
return ("stickerPack", [("emoticon", emoticon as Any), ("documents", documents as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_stickerPack(_ reader: BufferReader) -> StickerPack? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: [Int64]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.StickerPack.stickerPack(emoticon: _1!, documents: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum StickerSet: TypeConstructorDescription {
|
||||
case stickerSet(flags: Int32, installedDate: Int32?, id: Int64, accessHash: Int64, title: String, shortName: String, thumbs: [Api.PhotoSize]?, thumbDcId: Int32?, thumbVersion: Int32?, thumbDocumentId: Int64?, count: Int32, hash: Int32)
|
||||
|
||||
@ -218,6 +218,60 @@ public extension Api.payments {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.payments {
|
||||
enum StarGiftCollections: TypeConstructorDescription {
|
||||
case starGiftCollections(collections: [Api.StarGiftCollection])
|
||||
case starGiftCollectionsNotModified
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .starGiftCollections(let collections):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1977011469)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(collections.count))
|
||||
for item in collections {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .starGiftCollectionsNotModified:
|
||||
if boxed {
|
||||
buffer.appendInt32(-1598402793)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .starGiftCollections(let collections):
|
||||
return ("starGiftCollections", [("collections", collections as Any)])
|
||||
case .starGiftCollectionsNotModified:
|
||||
return ("starGiftCollectionsNotModified", [])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_starGiftCollections(_ reader: BufferReader) -> StarGiftCollections? {
|
||||
var _1: [Api.StarGiftCollection]?
|
||||
if let _ = reader.readInt32() {
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StarGiftCollection.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.payments.StarGiftCollections.starGiftCollections(collections: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_starGiftCollectionsNotModified(_ reader: BufferReader) -> StarGiftCollections? {
|
||||
return Api.payments.StarGiftCollections.starGiftCollectionsNotModified
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.payments {
|
||||
enum StarGiftUpgradePreview: TypeConstructorDescription {
|
||||
case starGiftUpgradePreview(sampleAttributes: [Api.StarGiftAttribute])
|
||||
@ -1758,197 +1812,3 @@ public extension Api.stats {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.stats {
|
||||
enum MegagroupStats: TypeConstructorDescription {
|
||||
case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-276825834)
|
||||
}
|
||||
period.serialize(buffer, true)
|
||||
members.serialize(buffer, true)
|
||||
messages.serialize(buffer, true)
|
||||
viewers.serialize(buffer, true)
|
||||
posters.serialize(buffer, true)
|
||||
growthGraph.serialize(buffer, true)
|
||||
membersGraph.serialize(buffer, true)
|
||||
newMembersBySourceGraph.serialize(buffer, true)
|
||||
languagesGraph.serialize(buffer, true)
|
||||
messagesGraph.serialize(buffer, true)
|
||||
actionsGraph.serialize(buffer, true)
|
||||
topHoursGraph.serialize(buffer, true)
|
||||
weekdaysGraph.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(topPosters.count))
|
||||
for item in topPosters {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(topAdmins.count))
|
||||
for item in topAdmins {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(topInviters.count))
|
||||
for item in topInviters {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
|
||||
return ("megagroupStats", [("period", period as Any), ("members", members as Any), ("messages", messages as Any), ("viewers", viewers as Any), ("posters", posters as Any), ("growthGraph", growthGraph as Any), ("membersGraph", membersGraph as Any), ("newMembersBySourceGraph", newMembersBySourceGraph as Any), ("languagesGraph", languagesGraph as Any), ("messagesGraph", messagesGraph as Any), ("actionsGraph", actionsGraph as Any), ("topHoursGraph", topHoursGraph as Any), ("weekdaysGraph", weekdaysGraph as Any), ("topPosters", topPosters as Any), ("topAdmins", topAdmins as Any), ("topInviters", topInviters as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_megagroupStats(_ reader: BufferReader) -> MegagroupStats? {
|
||||
var _1: Api.StatsDateRangeDays?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
|
||||
}
|
||||
var _2: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
var _3: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
var _4: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
var _5: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
var _6: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _7: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _8: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _9: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_9 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _10: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _11: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _12: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _13: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _14: [Api.StatsGroupTopPoster]?
|
||||
if let _ = reader.readInt32() {
|
||||
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self)
|
||||
}
|
||||
var _15: [Api.StatsGroupTopAdmin]?
|
||||
if let _ = reader.readInt32() {
|
||||
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self)
|
||||
}
|
||||
var _16: [Api.StatsGroupTopInviter]?
|
||||
if let _ = reader.readInt32() {
|
||||
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self)
|
||||
}
|
||||
var _17: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
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
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
let _c10 = _10 != nil
|
||||
let _c11 = _11 != nil
|
||||
let _c12 = _12 != nil
|
||||
let _c13 = _13 != nil
|
||||
let _c14 = _14 != nil
|
||||
let _c15 = _15 != nil
|
||||
let _c16 = _16 != nil
|
||||
let _c17 = _17 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
|
||||
return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.stats {
|
||||
enum MessageStats: TypeConstructorDescription {
|
||||
case messageStats(viewsGraph: Api.StatsGraph, reactionsByEmotionGraph: Api.StatsGraph)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .messageStats(let viewsGraph, let reactionsByEmotionGraph):
|
||||
if boxed {
|
||||
buffer.appendInt32(2145983508)
|
||||
}
|
||||
viewsGraph.serialize(buffer, true)
|
||||
reactionsByEmotionGraph.serialize(buffer, true)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .messageStats(let viewsGraph, let reactionsByEmotionGraph):
|
||||
return ("messageStats", [("viewsGraph", viewsGraph as Any), ("reactionsByEmotionGraph", reactionsByEmotionGraph as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? {
|
||||
var _1: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _2: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.stats.MessageStats.messageStats(viewsGraph: _1!, reactionsByEmotionGraph: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,197 @@
|
||||
public extension Api.stats {
|
||||
enum MegagroupStats: TypeConstructorDescription {
|
||||
case megagroupStats(period: Api.StatsDateRangeDays, members: Api.StatsAbsValueAndPrev, messages: Api.StatsAbsValueAndPrev, viewers: Api.StatsAbsValueAndPrev, posters: Api.StatsAbsValueAndPrev, growthGraph: Api.StatsGraph, membersGraph: Api.StatsGraph, newMembersBySourceGraph: Api.StatsGraph, languagesGraph: Api.StatsGraph, messagesGraph: Api.StatsGraph, actionsGraph: Api.StatsGraph, topHoursGraph: Api.StatsGraph, weekdaysGraph: Api.StatsGraph, topPosters: [Api.StatsGroupTopPoster], topAdmins: [Api.StatsGroupTopAdmin], topInviters: [Api.StatsGroupTopInviter], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-276825834)
|
||||
}
|
||||
period.serialize(buffer, true)
|
||||
members.serialize(buffer, true)
|
||||
messages.serialize(buffer, true)
|
||||
viewers.serialize(buffer, true)
|
||||
posters.serialize(buffer, true)
|
||||
growthGraph.serialize(buffer, true)
|
||||
membersGraph.serialize(buffer, true)
|
||||
newMembersBySourceGraph.serialize(buffer, true)
|
||||
languagesGraph.serialize(buffer, true)
|
||||
messagesGraph.serialize(buffer, true)
|
||||
actionsGraph.serialize(buffer, true)
|
||||
topHoursGraph.serialize(buffer, true)
|
||||
weekdaysGraph.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(topPosters.count))
|
||||
for item in topPosters {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(topAdmins.count))
|
||||
for item in topAdmins {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(topInviters.count))
|
||||
for item in topInviters {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .megagroupStats(let period, let members, let messages, let viewers, let posters, let growthGraph, let membersGraph, let newMembersBySourceGraph, let languagesGraph, let messagesGraph, let actionsGraph, let topHoursGraph, let weekdaysGraph, let topPosters, let topAdmins, let topInviters, let users):
|
||||
return ("megagroupStats", [("period", period as Any), ("members", members as Any), ("messages", messages as Any), ("viewers", viewers as Any), ("posters", posters as Any), ("growthGraph", growthGraph as Any), ("membersGraph", membersGraph as Any), ("newMembersBySourceGraph", newMembersBySourceGraph as Any), ("languagesGraph", languagesGraph as Any), ("messagesGraph", messagesGraph as Any), ("actionsGraph", actionsGraph as Any), ("topHoursGraph", topHoursGraph as Any), ("weekdaysGraph", weekdaysGraph as Any), ("topPosters", topPosters as Any), ("topAdmins", topAdmins as Any), ("topInviters", topInviters as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_megagroupStats(_ reader: BufferReader) -> MegagroupStats? {
|
||||
var _1: Api.StatsDateRangeDays?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.StatsDateRangeDays
|
||||
}
|
||||
var _2: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
var _3: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_3 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
var _4: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
var _5: Api.StatsAbsValueAndPrev?
|
||||
if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.StatsAbsValueAndPrev
|
||||
}
|
||||
var _6: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _7: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _8: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _9: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_9 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _10: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_10 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _11: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_11 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _12: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_12 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _13: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_13 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _14: [Api.StatsGroupTopPoster]?
|
||||
if let _ = reader.readInt32() {
|
||||
_14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopPoster.self)
|
||||
}
|
||||
var _15: [Api.StatsGroupTopAdmin]?
|
||||
if let _ = reader.readInt32() {
|
||||
_15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopAdmin.self)
|
||||
}
|
||||
var _16: [Api.StatsGroupTopInviter]?
|
||||
if let _ = reader.readInt32() {
|
||||
_16 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StatsGroupTopInviter.self)
|
||||
}
|
||||
var _17: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_17 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
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
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
let _c10 = _10 != nil
|
||||
let _c11 = _11 != nil
|
||||
let _c12 = _12 != nil
|
||||
let _c13 = _13 != nil
|
||||
let _c14 = _14 != nil
|
||||
let _c15 = _15 != nil
|
||||
let _c16 = _16 != nil
|
||||
let _c17 = _17 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 {
|
||||
return Api.stats.MegagroupStats.megagroupStats(period: _1!, members: _2!, messages: _3!, viewers: _4!, posters: _5!, growthGraph: _6!, membersGraph: _7!, newMembersBySourceGraph: _8!, languagesGraph: _9!, messagesGraph: _10!, actionsGraph: _11!, topHoursGraph: _12!, weekdaysGraph: _13!, topPosters: _14!, topAdmins: _15!, topInviters: _16!, users: _17!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.stats {
|
||||
enum MessageStats: TypeConstructorDescription {
|
||||
case messageStats(viewsGraph: Api.StatsGraph, reactionsByEmotionGraph: Api.StatsGraph)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .messageStats(let viewsGraph, let reactionsByEmotionGraph):
|
||||
if boxed {
|
||||
buffer.appendInt32(2145983508)
|
||||
}
|
||||
viewsGraph.serialize(buffer, true)
|
||||
reactionsByEmotionGraph.serialize(buffer, true)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .messageStats(let viewsGraph, let reactionsByEmotionGraph):
|
||||
return ("messageStats", [("viewsGraph", viewsGraph as Any), ("reactionsByEmotionGraph", reactionsByEmotionGraph as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_messageStats(_ reader: BufferReader) -> MessageStats? {
|
||||
var _1: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_1 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
var _2: Api.StatsGraph?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.StatsGraph
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.stats.MessageStats.messageStats(viewsGraph: _1!, reactionsByEmotionGraph: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.stats {
|
||||
enum PublicForwards: TypeConstructorDescription {
|
||||
case publicForwards(flags: Int32, count: Int32, forwards: [Api.PublicForward], nextOffset: String?, chats: [Api.Chat], users: [Api.User])
|
||||
@ -1286,59 +1480,3 @@ public extension Api.updates {
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.upload {
|
||||
enum CdnFile: TypeConstructorDescription {
|
||||
case cdnFile(bytes: Buffer)
|
||||
case cdnFileReuploadNeeded(requestToken: Buffer)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .cdnFile(let bytes):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1449145777)
|
||||
}
|
||||
serializeBytes(bytes, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .cdnFileReuploadNeeded(let requestToken):
|
||||
if boxed {
|
||||
buffer.appendInt32(-290921362)
|
||||
}
|
||||
serializeBytes(requestToken, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .cdnFile(let bytes):
|
||||
return ("cdnFile", [("bytes", bytes as Any)])
|
||||
case .cdnFileReuploadNeeded(let requestToken):
|
||||
return ("cdnFileReuploadNeeded", [("requestToken", requestToken as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_cdnFile(_ reader: BufferReader) -> CdnFile? {
|
||||
var _1: Buffer?
|
||||
_1 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.upload.CdnFile.cdnFile(bytes: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_cdnFileReuploadNeeded(_ reader: BufferReader) -> CdnFile? {
|
||||
var _1: Buffer?
|
||||
_1 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.upload.CdnFile.cdnFileReuploadNeeded(requestToken: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,59 @@
|
||||
public extension Api.upload {
|
||||
enum CdnFile: TypeConstructorDescription {
|
||||
case cdnFile(bytes: Buffer)
|
||||
case cdnFileReuploadNeeded(requestToken: Buffer)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .cdnFile(let bytes):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1449145777)
|
||||
}
|
||||
serializeBytes(bytes, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .cdnFileReuploadNeeded(let requestToken):
|
||||
if boxed {
|
||||
buffer.appendInt32(-290921362)
|
||||
}
|
||||
serializeBytes(requestToken, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .cdnFile(let bytes):
|
||||
return ("cdnFile", [("bytes", bytes as Any)])
|
||||
case .cdnFileReuploadNeeded(let requestToken):
|
||||
return ("cdnFileReuploadNeeded", [("requestToken", requestToken as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_cdnFile(_ reader: BufferReader) -> CdnFile? {
|
||||
var _1: Buffer?
|
||||
_1 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.upload.CdnFile.cdnFile(bytes: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_cdnFileReuploadNeeded(_ reader: BufferReader) -> CdnFile? {
|
||||
var _1: Buffer?
|
||||
_1 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.upload.CdnFile.cdnFileReuploadNeeded(requestToken: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.upload {
|
||||
enum File: TypeConstructorDescription {
|
||||
case file(type: Api.storage.FileType, mtime: Int32, bytes: Buffer)
|
||||
|
||||
@ -9326,6 +9326,43 @@ public extension Api.functions.payments {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func createStarGiftCollection(peer: Api.InputPeer, title: String, stargift: [Api.InputSavedStarGift]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.StarGiftCollection>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(524947079)
|
||||
peer.serialize(buffer, true)
|
||||
serializeString(title, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(stargift.count))
|
||||
for item in stargift {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
return (FunctionDescription(name: "payments.createStarGiftCollection", parameters: [("peer", String(describing: peer)), ("title", String(describing: title)), ("stargift", String(describing: stargift))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StarGiftCollection? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.StarGiftCollection?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.StarGiftCollection
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func deleteStarGiftCollection(peer: Api.InputPeer, collectionId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1386854168)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(collectionId, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "payments.deleteStarGiftCollection", parameters: [("peer", String(describing: peer)), ("collectionId", String(describing: collectionId))]), 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 editConnectedStarRefBot(flags: Int32, peer: Api.InputPeer, link: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.ConnectedStarRefBots>) {
|
||||
let buffer = Buffer()
|
||||
@ -9548,14 +9585,15 @@ public extension Api.functions.payments {
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func getSavedStarGifts(flags: Int32, peer: Api.InputPeer, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.SavedStarGifts>) {
|
||||
static func getSavedStarGifts(flags: Int32, peer: Api.InputPeer, collectionId: Int32?, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.SavedStarGifts>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(595791337)
|
||||
buffer.appendInt32(-1558583959)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 6) != 0 {serializeInt32(collectionId!, buffer: buffer, boxed: false)}
|
||||
serializeString(offset, buffer: buffer, boxed: false)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "payments.getSavedStarGifts", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.SavedStarGifts? in
|
||||
return (FunctionDescription(name: "payments.getSavedStarGifts", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("collectionId", String(describing: collectionId)), ("offset", String(describing: offset)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.SavedStarGifts? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.payments.SavedStarGifts?
|
||||
if let signature = reader.readInt32() {
|
||||
@ -9565,6 +9603,22 @@ public extension Api.functions.payments {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func getStarGiftCollections(peer: Api.InputPeer, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarGiftCollections>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1743023651)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "payments.getStarGiftCollections", parameters: [("peer", String(describing: peer)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.StarGiftCollections? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.payments.StarGiftCollections?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.payments.StarGiftCollections
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func getStarGiftUpgradePreview(giftId: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.StarGiftUpgradePreview>) {
|
||||
let buffer = Buffer()
|
||||
@ -9845,6 +9899,26 @@ public extension Api.functions.payments {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func reorderStarGiftCollections(peer: Api.InputPeer, order: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1020594996)
|
||||
peer.serialize(buffer, true)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(order.count))
|
||||
for item in order {
|
||||
serializeInt32(item, buffer: buffer, boxed: false)
|
||||
}
|
||||
return (FunctionDescription(name: "payments.reorderStarGiftCollections", parameters: [("peer", String(describing: peer)), ("order", String(describing: order))]), 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 saveStarGift(flags: Int32, stargift: Api.InputSavedStarGift) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
@ -9950,6 +10024,39 @@ public extension Api.functions.payments {
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func updateStarGiftCollection(flags: Int32, peer: Api.InputPeer, collectionId: Int32, title: String?, deleteStargift: [Api.InputSavedStarGift]?, addStargift: [Api.InputSavedStarGift]?, order: [Api.InputSavedStarGift]?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.StarGiftCollection>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1339932391)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(collectionId, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(title!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(deleteStargift!.count))
|
||||
for item in deleteStargift! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 2) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(addStargift!.count))
|
||||
for item in addStargift! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(order!.count))
|
||||
for item in order! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
return (FunctionDescription(name: "payments.updateStarGiftCollection", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("collectionId", String(describing: collectionId)), ("title", String(describing: title)), ("deleteStargift", String(describing: deleteStargift)), ("addStargift", String(describing: addStargift)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.StarGiftCollection? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.StarGiftCollection?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.StarGiftCollection
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.payments {
|
||||
static func updateStarGiftPrice(stargift: Api.InputSavedStarGift, resellStars: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
|
||||
@ -284,13 +284,14 @@ func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: Refere
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
|
||||
switch replyTo {
|
||||
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, _):
|
||||
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId):
|
||||
let _ = replyHeader
|
||||
let _ = replyMedia
|
||||
let _ = replyToTopId
|
||||
let _ = quoteText
|
||||
let _ = quoteEntities
|
||||
let _ = quoteOffset
|
||||
let _ = todoItemId
|
||||
|
||||
if let replyToMsgId = replyToMsgId {
|
||||
let targetId = MessageId(peerId: replyToPeerId?.peerId ?? peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
|
||||
@ -307,13 +308,14 @@ func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: Refere
|
||||
case let .messageService(_, id, _, chatPeerId, _, replyHeader, _, _, _, _):
|
||||
if let replyHeader = replyHeader {
|
||||
switch replyHeader {
|
||||
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, _):
|
||||
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId):
|
||||
let _ = replyHeader
|
||||
let _ = replyMedia
|
||||
let _ = replyToTopId
|
||||
let _ = quoteText
|
||||
let _ = quoteEntities
|
||||
let _ = quoteOffset
|
||||
let _ = todoItemId
|
||||
|
||||
if let replyToMsgId = replyToMsgId {
|
||||
let targetId = MessageId(peerId: replyToPeerId?.peerId ?? chatPeerId.peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
|
||||
@ -723,7 +725,7 @@ extension StoreMessage {
|
||||
if let replyTo = replyTo {
|
||||
var threadMessageId: MessageId?
|
||||
switch replyTo {
|
||||
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, _):
|
||||
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId):
|
||||
let isForumTopic = (innerFlags & (1 << 3)) != 0
|
||||
|
||||
var quote: EngineMessageReplyQuote?
|
||||
@ -766,7 +768,7 @@ extension StoreMessage {
|
||||
threadId = Int64(threadIdValue.id)
|
||||
}
|
||||
}
|
||||
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote, isQuote: isQuote))
|
||||
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote, isQuote: isQuote, todoItemId: todoItemId))
|
||||
}
|
||||
if let replyHeader = replyHeader {
|
||||
attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote, isQuote: isQuote))
|
||||
@ -1084,7 +1086,7 @@ extension StoreMessage {
|
||||
|
||||
if chatPeerId.peerId.namespace == Namespaces.Peer.CloudChannel, let replyTo {
|
||||
switch replyTo {
|
||||
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, _, quoteText, quoteEntities, quoteOffset, _):
|
||||
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, _, quoteText, quoteEntities, quoteOffset, todoItemId):
|
||||
var quote: EngineMessageReplyQuote?
|
||||
let isQuote = (innerFlags & (1 << 9)) != 0
|
||||
if quoteText != nil || replyMedia != nil {
|
||||
@ -1093,7 +1095,7 @@ extension StoreMessage {
|
||||
|
||||
if let replyToMsgId = replyToMsgId {
|
||||
let replyPeerId = replyToPeerId?.peerId ?? peerId
|
||||
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: nil, quote: quote, isQuote: isQuote))
|
||||
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: nil, quote: quote, isQuote: isQuote, todoItemId: todoItemId))
|
||||
} else if let replyHeader = replyHeader {
|
||||
attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote, isQuote: isQuote))
|
||||
}
|
||||
@ -1104,7 +1106,7 @@ extension StoreMessage {
|
||||
} else if let replyTo = replyTo {
|
||||
var threadMessageId: MessageId?
|
||||
switch replyTo {
|
||||
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, _):
|
||||
case let .messageReplyHeader(innerFlags, replyToMsgId, replyToPeerId, replyHeader, replyMedia, replyToTopId, quoteText, quoteEntities, quoteOffset, todoItemId):
|
||||
var quote: EngineMessageReplyQuote?
|
||||
let isQuote = (innerFlags & (1 << 9)) != 0
|
||||
if quoteText != nil || replyMedia != nil {
|
||||
@ -1130,7 +1132,7 @@ extension StoreMessage {
|
||||
default:
|
||||
break
|
||||
}
|
||||
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote, isQuote: isQuote))
|
||||
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote, isQuote: isQuote, todoItemId: todoItemId))
|
||||
} else if let replyHeader = replyHeader {
|
||||
attributes.append(QuotedReplyMessageAttribute(apiHeader: replyHeader, quote: quote, isQuote: isQuote))
|
||||
}
|
||||
|
||||
@ -82,10 +82,12 @@ public struct EngineMessageReplyQuote: Codable, Equatable {
|
||||
public struct EngineMessageReplySubject: Codable, Equatable {
|
||||
public var messageId: EngineMessage.Id
|
||||
public var quote: EngineMessageReplyQuote?
|
||||
public var todoItemId: Int32?
|
||||
|
||||
public init(messageId: EngineMessage.Id, quote: EngineMessageReplyQuote?) {
|
||||
public init(messageId: EngineMessage.Id, quote: EngineMessageReplyQuote?, todoItemId: Int32?) {
|
||||
self.messageId = messageId
|
||||
self.quote = quote
|
||||
self.todoItemId = todoItemId
|
||||
}
|
||||
}
|
||||
|
||||
@ -385,7 +387,7 @@ public func enqueueMessagesToMultiplePeers(account: Account, peerIds: [PeerId],
|
||||
for peerId in peerIds {
|
||||
var replyToMessageId: EngineMessageReplySubject?
|
||||
if let threadIds = threadIds[peerId] {
|
||||
replyToMessageId = EngineMessageReplySubject(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadIds)), quote: nil)
|
||||
replyToMessageId = EngineMessageReplySubject(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadIds)), quote: nil, todoItemId: nil)
|
||||
}
|
||||
var messages = messages
|
||||
if let replyToMessageId = replyToMessageId {
|
||||
@ -431,7 +433,7 @@ public func resendMessages(account: Account, messageIds: [MessageId]) -> Signal<
|
||||
var forwardSource: MessageId?
|
||||
inner: for attribute in message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
replyToMessageId = EngineMessageReplySubject(messageId: attribute.messageId, quote: attribute.quote)
|
||||
replyToMessageId = EngineMessageReplySubject(messageId: attribute.messageId, quote: attribute.quote, todoItemId: attribute.todoItemId)
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
replyToStoryId = attribute.storyId
|
||||
} else if let attribute = attribute as? OutgoingMessageInfoAttribute {
|
||||
@ -526,7 +528,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
mediaReference = .standalone(media: media)
|
||||
}
|
||||
}
|
||||
updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, inlineStickers: [:], mediaReference: mediaReference, threadId: threadId, replyToMessageId: threadId.flatMap { EngineMessageReplySubject(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: $0)), quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])))
|
||||
updatedMessages.append((transformedMedia, .message(text: sourceMessage.text, attributes: sourceMessage.attributes, inlineStickers: [:], mediaReference: mediaReference, threadId: threadId, replyToMessageId: threadId.flatMap { EngineMessageReplySubject(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: $0)), quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])))
|
||||
continue outer
|
||||
}
|
||||
}
|
||||
@ -659,7 +661,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
||||
quote = EngineMessageReplyQuote(text: replyMessage.text, offset: nil, entities: messageTextEntitiesInRange(entities: replyMessage.textEntitiesAttribute?.entities ?? [], range: NSRange(location: 0, length: nsText.length), onlyQuoteable: true), media: replyMedia)
|
||||
}
|
||||
}
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyToMessageId.messageId, threadMessageId: threadMessageId, quote: quote, isQuote: isQuote))
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyToMessageId.messageId, threadMessageId: threadMessageId, quote: quote, isQuote: isQuote, todoItemId: replyToMessageId.todoItemId))
|
||||
}
|
||||
if let replyToStoryId = replyToStoryId {
|
||||
attributes.append(ReplyStoryAttribute(storyId: replyToStoryId))
|
||||
|
||||
@ -171,7 +171,7 @@ public func standaloneSendEnqueueMessages(
|
||||
}
|
||||
|
||||
if let replyToMessageId = message.replyToMessageId {
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyToMessageId, threadMessageId: nil, quote: nil, isQuote: false))
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyToMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil))
|
||||
}
|
||||
if let forwardOptions = message.forwardOptions {
|
||||
attributes.append(ForwardOptionsMessageAttribute(hideNames: forwardOptions.hideNames, hideCaptions: forwardOptions.hideCaptions))
|
||||
@ -338,6 +338,7 @@ private func sendUploadedMessageContent(
|
||||
}
|
||||
}
|
||||
var replyToStoryId: StoryId?
|
||||
var replyTodoItemId: Int32?
|
||||
var scheduleTime: Int32?
|
||||
var videoTimestamp: Int32?
|
||||
var sendAsPeerId: PeerId?
|
||||
@ -350,6 +351,7 @@ private func sendUploadedMessageContent(
|
||||
for attribute in attributes {
|
||||
if let replyAttribute = attribute as? ReplyMessageAttribute {
|
||||
replyMessageId = replyAttribute.messageId.id
|
||||
replyTodoItemId = replyAttribute.todoItemId
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
replyToStoryId = attribute.storyId
|
||||
} else if let outgoingInfo = attribute as? OutgoingMessageInfoAttribute {
|
||||
@ -435,7 +437,10 @@ private func sendUploadedMessageContent(
|
||||
if monoforumPeerId != nil {
|
||||
replyFlags |= 1 << 5
|
||||
}
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: nil)
|
||||
if let _ = replyTodoItemId {
|
||||
replyFlags |= 1 << 6
|
||||
}
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
|
||||
} else if let replyToStoryId {
|
||||
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
|
||||
flags |= 1 << 0
|
||||
@ -466,7 +471,10 @@ private func sendUploadedMessageContent(
|
||||
if monoforumPeerId != nil {
|
||||
replyFlags |= 1 << 5
|
||||
}
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: nil)
|
||||
if let _ = replyTodoItemId {
|
||||
replyFlags |= 1 << 6
|
||||
}
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
|
||||
} else if let replyToStoryId = replyToStoryId {
|
||||
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
|
||||
flags |= 1 << 0
|
||||
@ -693,7 +701,7 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
|
||||
replyTo = .inputReplyToMessage(flags: flags, replyToMsgId: threadId, topMsgId: threadId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil)
|
||||
}
|
||||
|
||||
sendMessageRequest = account.network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, allowPaidStars: allowPaidStars, suggestedPost: nil))
|
||||
sendMessageRequest = account.network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, allowPaidStars: allowPaidStars, suggestedPost: nil))
|
||||
|> `catch` { _ -> Signal<Api.Updates, NoError> in
|
||||
return .complete()
|
||||
}
|
||||
|
||||
@ -1595,7 +1595,7 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
||||
}
|
||||
if let replyToMsgHeader {
|
||||
switch replyToMsgHeader {
|
||||
case let .inputReplyToMessage(_, replyToMsgId, topMsgId, replyToPeerId, quoteText, quoteEntities, quoteOffset, monoforumPeerId, _):
|
||||
case let .inputReplyToMessage(_, replyToMsgId, topMsgId, replyToPeerId, quoteText, quoteEntities, quoteOffset, monoforumPeerId, todoItemId):
|
||||
let _ = topMsgId
|
||||
let _ = monoforumPeerId
|
||||
|
||||
@ -1631,7 +1631,8 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
||||
|
||||
replySubject = EngineMessageReplySubject(
|
||||
messageId: MessageId(peerId: parsedReplyToPeerId ?? peer.peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId),
|
||||
quote: quote
|
||||
quote: quote,
|
||||
todoItemId: todoItemId
|
||||
)
|
||||
case .inputReplyToStory:
|
||||
break
|
||||
|
||||
@ -197,6 +197,8 @@ private func synchronizeChatInputState(transaction: Transaction, postbox: Postbo
|
||||
}
|
||||
}
|
||||
|
||||
let replyTodoItemId = replySubject.todoItemId
|
||||
|
||||
if replyToPeer != nil {
|
||||
innerFlags |= 1 << 1
|
||||
}
|
||||
@ -209,9 +211,11 @@ private func synchronizeChatInputState(transaction: Transaction, postbox: Postbo
|
||||
if quoteOffset != nil {
|
||||
innerFlags |= 1 << 4
|
||||
}
|
||||
|
||||
if let _ = replyTodoItemId {
|
||||
innerFlags |= 1 << 6
|
||||
}
|
||||
if !discard {
|
||||
replyTo = .inputReplyToMessage(flags: innerFlags, replyToMsgId: replySubject.messageId.id, topMsgId: topMsgId, replyToPeerId: replyToPeer, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: nil)
|
||||
replyTo = .inputReplyToMessage(flags: innerFlags, replyToMsgId: replySubject.messageId.id, topMsgId: topMsgId, replyToPeerId: replyToPeer, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
|
||||
}
|
||||
} else if let topMsgId {
|
||||
flags |= 1 << 0
|
||||
|
||||
@ -854,6 +854,7 @@ public final class PendingMessageManager {
|
||||
var replyPeerId: PeerId?
|
||||
var replyQuote: EngineMessageReplyQuote?
|
||||
var replyToStoryId: StoryId?
|
||||
var replyTodoItemId: Int32?
|
||||
var scheduleTime: Int32?
|
||||
var videoTimestamp: Int32?
|
||||
var sendAsPeerId: PeerId?
|
||||
@ -873,6 +874,7 @@ public final class PendingMessageManager {
|
||||
if replyAttribute.isQuote {
|
||||
replyQuote = replyAttribute.quote
|
||||
}
|
||||
replyTodoItemId = replyAttribute.todoItemId
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
replyToStoryId = attribute.storyId
|
||||
} else if let _ = attribute as? ForwardSourceInfoAttribute {
|
||||
@ -1108,7 +1110,11 @@ public final class PendingMessageManager {
|
||||
}
|
||||
}
|
||||
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: replyToPeerId, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: nil)
|
||||
if let _ = replyTodoItemId {
|
||||
replyFlags |= 1 << 6
|
||||
}
|
||||
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: replyToPeerId, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
|
||||
} else if let replyToStoryId {
|
||||
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
|
||||
flags |= 1 << 0
|
||||
@ -1349,6 +1355,7 @@ public final class PendingMessageManager {
|
||||
var replyPeerId: PeerId?
|
||||
var replyQuote: EngineMessageReplyQuote?
|
||||
var replyToStoryId: StoryId?
|
||||
var replyTodoItemId: Int32?
|
||||
var scheduleTime: Int32?
|
||||
var videoTimestamp: Int32?
|
||||
var sendAsPeerId: PeerId?
|
||||
@ -1381,6 +1388,7 @@ public final class PendingMessageManager {
|
||||
if replyAttribute.isQuote {
|
||||
replyQuote = replyAttribute.quote
|
||||
}
|
||||
replyTodoItemId = replyAttribute.todoItemId
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
replyToStoryId = attribute.storyId
|
||||
} else if let outgoingInfo = attribute as? OutgoingMessageInfoAttribute {
|
||||
@ -1490,9 +1498,10 @@ public final class PendingMessageManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: replyToPeerId, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: nil)
|
||||
if let _ = replyTodoItemId {
|
||||
replyFlags |= 1 << 6
|
||||
}
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: replyToPeerId, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
|
||||
} else if let replyToStoryId = replyToStoryId {
|
||||
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
|
||||
flags |= 1 << 0
|
||||
@ -1586,8 +1595,11 @@ public final class PendingMessageManager {
|
||||
quoteEntities = apiEntitiesFromMessageTextEntities(replyQuote.entities, associatedPeers: associatedPeers)
|
||||
}
|
||||
}
|
||||
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: replyToPeerId, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: nil)
|
||||
|
||||
if let _ = replyTodoItemId {
|
||||
replyFlags |= 1 << 6
|
||||
}
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: topMsgId, replyToPeerId: replyToPeerId, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
|
||||
} else if let replyToStoryId = replyToStoryId {
|
||||
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
|
||||
flags |= 1 << 0
|
||||
@ -1731,8 +1743,11 @@ public final class PendingMessageManager {
|
||||
quoteEntities = apiEntitiesFromMessageTextEntities(replyQuote.entities, associatedPeers: associatedPeers)
|
||||
}
|
||||
}
|
||||
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: message.threadId.flatMap(Int32.init(clamping:)), replyToPeerId: replyToPeerId, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: nil)
|
||||
|
||||
if let _ = replyTodoItemId {
|
||||
replyFlags |= 1 << 6
|
||||
}
|
||||
replyTo = .inputReplyToMessage(flags: replyFlags, replyToMsgId: replyMessageId, topMsgId: message.threadId.flatMap(Int32.init(clamping:)), replyToPeerId: replyToPeerId, quoteText: quoteText, quoteEntities: quoteEntities, quoteOffset: quoteOffset, monoforumPeerId: monoforumPeerId, todoItemId: replyTodoItemId)
|
||||
} else if let replyToStoryId = replyToStoryId {
|
||||
if let inputPeer = transaction.getPeer(replyToStoryId.peerId).flatMap(apiInputPeer) {
|
||||
flags |= 1 << 0
|
||||
|
||||
@ -881,7 +881,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
}
|
||||
|
||||
if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) {
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false))
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil))
|
||||
}
|
||||
|
||||
var entitiesAttribute: TextEntitiesMessageAttribute?
|
||||
@ -1113,7 +1113,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
}
|
||||
|
||||
if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) {
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false))
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil))
|
||||
}
|
||||
|
||||
var entitiesAttribute: TextEntitiesMessageAttribute?
|
||||
@ -1392,7 +1392,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
}
|
||||
|
||||
if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) {
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false))
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil))
|
||||
}
|
||||
|
||||
var entitiesAttribute: TextEntitiesMessageAttribute?
|
||||
@ -1593,7 +1593,7 @@ private func parseMessage(peerId: PeerId, authorId: PeerId, tagLocalIndex: Int32
|
||||
}
|
||||
|
||||
if let replyToRandomId = replyToRandomId, let replyMessageId = messageIdForGloballyUniqueMessageId(replyToRandomId) {
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false))
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil))
|
||||
}
|
||||
|
||||
var entitiesAttribute: TextEntitiesMessageAttribute?
|
||||
|
||||
@ -144,6 +144,7 @@ public struct Namespaces {
|
||||
public static let channelsForPublicReaction: Int8 = 45
|
||||
public static let cachedGroupsInCommon: Int8 = 46
|
||||
public static let groupCallPersistentSettings: Int8 = 47
|
||||
public static let cachedProfileGiftsCollections: Int8 = 48
|
||||
}
|
||||
|
||||
public struct UnorderedItemList {
|
||||
|
||||
@ -7,16 +7,18 @@ public class ReplyMessageAttribute: MessageAttribute {
|
||||
public let threadMessageId: MessageId?
|
||||
public let quote: EngineMessageReplyQuote?
|
||||
public let isQuote: Bool
|
||||
public let todoItemId: Int32?
|
||||
|
||||
public var associatedMessageIds: [MessageId] {
|
||||
return [self.messageId]
|
||||
}
|
||||
|
||||
public init(messageId: MessageId, threadMessageId: MessageId?, quote: EngineMessageReplyQuote?, isQuote: Bool) {
|
||||
public init(messageId: MessageId, threadMessageId: MessageId?, quote: EngineMessageReplyQuote?, isQuote: Bool, todoItemId: Int32?) {
|
||||
self.messageId = messageId
|
||||
self.threadMessageId = threadMessageId
|
||||
self.quote = quote
|
||||
self.isQuote = isQuote
|
||||
self.todoItemId = todoItemId
|
||||
}
|
||||
|
||||
required public init(decoder: PostboxDecoder) {
|
||||
@ -31,6 +33,7 @@ public class ReplyMessageAttribute: MessageAttribute {
|
||||
|
||||
self.quote = decoder.decodeCodable(EngineMessageReplyQuote.self, forKey: "qu")
|
||||
self.isQuote = decoder.decodeBoolForKey("iq", orElse: self.quote != nil)
|
||||
self.todoItemId = decoder.decodeOptionalInt32ForKey("tid")
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
@ -48,6 +51,11 @@ public class ReplyMessageAttribute: MessageAttribute {
|
||||
encoder.encodeNil(forKey: "qu")
|
||||
}
|
||||
encoder.encodeBool(self.isQuote, forKey: "iq")
|
||||
if let todoItemId = self.todoItemId {
|
||||
encoder.encodeInt32(todoItemId, forKey: "tid")
|
||||
} else {
|
||||
encoder.encodeNil(forKey: "tid")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ public struct SynchronizeableChatInputState: Codable, Equatable {
|
||||
self.replySubject = replySubject
|
||||
} else {
|
||||
if let messageIdPeerId = try? container.decodeIfPresent(Int64.self, forKey: "m.p"), let messageIdNamespace = try? container.decodeIfPresent(Int32.self, forKey: "m.n"), let messageIdId = try? container.decodeIfPresent(Int32.self, forKey: "m.i") {
|
||||
self.replySubject = EngineMessageReplySubject(messageId: MessageId(peerId: PeerId(messageIdPeerId), namespace: messageIdNamespace, id: messageIdId), quote: nil)
|
||||
self.replySubject = EngineMessageReplySubject(messageId: MessageId(peerId: PeerId(messageIdPeerId), namespace: messageIdNamespace, id: messageIdId), quote: nil, todoItemId: nil)
|
||||
} else {
|
||||
self.replySubject = nil
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ func _internal_enqueueOutgoingMessageWithChatContextResult(account: Account, to
|
||||
func _internal_outgoingMessageWithChatContextResult(to peerId: PeerId, threadId: Int64?, botId: PeerId, result: ChatContextResult, replyToMessageId: EngineMessageReplySubject?, replyToStoryId: StoryId?, hideVia: Bool, silentPosting: Bool, scheduleTime: Int32?, sendPaidMessageStars: StarsAmount?, postpone: Bool, correlationId: Int64?) -> EnqueueMessage? {
|
||||
var replyToMessageId = replyToMessageId
|
||||
if replyToMessageId == nil, let threadId = threadId {
|
||||
replyToMessageId = EngineMessageReplySubject(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: MessageId.Id(clamping: threadId)), quote: nil)
|
||||
replyToMessageId = EngineMessageReplySubject(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: MessageId.Id(clamping: threadId)), quote: nil, todoItemId: nil)
|
||||
}
|
||||
|
||||
var webpageUrl: String?
|
||||
|
||||
@ -42,6 +42,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
}
|
||||
|
||||
public static let isBirthdayGift = Flags(rawValue: 1 << 0)
|
||||
public static let requiresPremium = Flags(rawValue: 1 << 1)
|
||||
}
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@ -55,6 +56,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
case flags
|
||||
case upgradeStars
|
||||
case releasedBy
|
||||
case perUserLimit
|
||||
}
|
||||
|
||||
public struct Availability: Equatable, Codable, PostboxCoding {
|
||||
@ -137,6 +139,31 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
}
|
||||
}
|
||||
|
||||
public struct PerUserLimit: Equatable, Codable, PostboxCoding {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case total
|
||||
case remains
|
||||
}
|
||||
|
||||
public let total: Int32
|
||||
public let remains: Int32
|
||||
|
||||
public init(total: Int32, remains: Int32) {
|
||||
self.total = total
|
||||
self.remains = remains
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
self.total = decoder.decodeInt32ForKey(CodingKeys.total.rawValue, orElse: 0)
|
||||
self.remains = decoder.decodeInt32ForKey(CodingKeys.remains.rawValue, orElse: 0)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
encoder.encodeInt32(self.total, forKey: CodingKeys.total.rawValue)
|
||||
encoder.encodeInt32(self.remains, forKey: CodingKeys.remains.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public enum DecodingError: Error {
|
||||
case generic
|
||||
}
|
||||
@ -151,8 +178,9 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
public let flags: Flags
|
||||
public let upgradeStars: Int64?
|
||||
public let releasedBy: EnginePeer.Id?
|
||||
public let perUserLimit: PerUserLimit?
|
||||
|
||||
public init(id: Int64, title: String?, file: TelegramMediaFile, price: Int64, convertStars: Int64, availability: Availability?, soldOut: SoldOut?, flags: Flags, upgradeStars: Int64?, releasedBy: EnginePeer.Id?) {
|
||||
public init(id: Int64, title: String?, file: TelegramMediaFile, price: Int64, convertStars: Int64, availability: Availability?, soldOut: SoldOut?, flags: Flags, upgradeStars: Int64?, releasedBy: EnginePeer.Id?, perUserLimit: PerUserLimit?) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.file = file
|
||||
@ -163,6 +191,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
self.flags = flags
|
||||
self.upgradeStars = upgradeStars
|
||||
self.releasedBy = releasedBy
|
||||
self.perUserLimit = perUserLimit
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
@ -183,6 +212,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
self.flags = Flags(rawValue: try container .decodeIfPresent(Int32.self, forKey: .flags) ?? 0)
|
||||
self.upgradeStars = try container.decodeIfPresent(Int64.self, forKey: .upgradeStars)
|
||||
self.releasedBy = try container.decodeIfPresent(EnginePeer.Id.self, forKey: .releasedBy)
|
||||
self.perUserLimit = try container.decodeIfPresent(PerUserLimit.self, forKey: .perUserLimit)
|
||||
}
|
||||
|
||||
public init(decoder: PostboxDecoder) {
|
||||
@ -196,6 +226,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
self.flags = Flags(rawValue: decoder.decodeInt32ForKey(CodingKeys.flags.rawValue, orElse: 0))
|
||||
self.upgradeStars = decoder.decodeOptionalInt64ForKey(CodingKeys.upgradeStars.rawValue)
|
||||
self.releasedBy = decoder.decodeOptionalInt64ForKey(CodingKeys.releasedBy.rawValue).flatMap { EnginePeer.Id($0) }
|
||||
self.perUserLimit = decoder.decodeObjectForKey(CodingKeys.perUserLimit.rawValue, decoder: { StarGift.Gift.PerUserLimit(decoder: $0) }) as? StarGift.Gift.PerUserLimit
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
@ -215,6 +246,7 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
try container.encode(self.flags.rawValue, forKey: .flags)
|
||||
try container.encodeIfPresent(self.upgradeStars, forKey: .upgradeStars)
|
||||
try container.encodeIfPresent(self.releasedBy, forKey: .releasedBy)
|
||||
try container.encodeIfPresent(self.perUserLimit, forKey: .perUserLimit)
|
||||
}
|
||||
|
||||
public func encode(_ encoder: PostboxEncoder) {
|
||||
@ -248,6 +280,11 @@ public enum StarGift: Equatable, Codable, PostboxCoding {
|
||||
} else {
|
||||
encoder.encodeNil(forKey: CodingKeys.releasedBy.rawValue)
|
||||
}
|
||||
if let perUserLimit = self.perUserLimit {
|
||||
encoder.encodeObject(perUserLimit, forKey: CodingKeys.perUserLimit.rawValue)
|
||||
} else {
|
||||
encoder.encodeNil(forKey: CodingKeys.perUserLimit.rawValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -720,11 +757,14 @@ public extension StarGift {
|
||||
extension StarGift {
|
||||
init?(apiStarGift: Api.StarGift) {
|
||||
switch apiStarGift {
|
||||
case let .starGift(apiFlags, id, sticker, stars, availabilityRemains, availabilityTotal, availabilityResale, convertStars, firstSale, lastSale, upgradeStars, minResaleStars, title, releasedBy, _, _):
|
||||
case let .starGift(apiFlags, id, sticker, stars, availabilityRemains, availabilityTotal, availabilityResale, convertStars, firstSale, lastSale, upgradeStars, minResaleStars, title, releasedBy, perUserTotal, perUserRemains):
|
||||
var flags = StarGift.Gift.Flags()
|
||||
if (apiFlags & (1 << 2)) != 0 {
|
||||
flags.insert(.isBirthdayGift)
|
||||
}
|
||||
if (apiFlags & (1 << 7)) != 0 {
|
||||
flags.insert(.requiresPremium)
|
||||
}
|
||||
|
||||
var availability: StarGift.Gift.Availability?
|
||||
if let availabilityRemains, let availabilityTotal {
|
||||
@ -739,10 +779,14 @@ extension StarGift {
|
||||
if let firstSale, let lastSale {
|
||||
soldOut = StarGift.Gift.SoldOut(firstSale: firstSale, lastSale: lastSale)
|
||||
}
|
||||
var perUserLimit: StarGift.Gift.PerUserLimit?
|
||||
if let perUserTotal, let perUserRemains {
|
||||
perUserLimit = StarGift.Gift.PerUserLimit(total: perUserTotal, remains: perUserRemains)
|
||||
}
|
||||
guard let file = telegramMediaFileFromApiDocument(sticker, altDocuments: nil) else {
|
||||
return nil
|
||||
}
|
||||
self = .generic(StarGift.Gift(id: id, title: title, file: file, price: stars, convertStars: convertStars, availability: availability, soldOut: soldOut, flags: flags, upgradeStars: upgradeStars, releasedBy: releasedBy?.peerId))
|
||||
self = .generic(StarGift.Gift(id: id, title: title, file: file, price: stars, convertStars: convertStars, availability: availability, soldOut: soldOut, flags: flags, upgradeStars: upgradeStars, releasedBy: releasedBy?.peerId, perUserLimit: perUserLimit))
|
||||
case let .starGiftUnique(_, id, title, slug, num, ownerPeerId, ownerName, ownerAddress, attributes, availabilityIssued, availabilityTotal, giftAddress, resellStars, releasedBy):
|
||||
let owner: StarGift.UniqueGift.Owner
|
||||
if let ownerAddress {
|
||||
@ -1075,7 +1119,7 @@ func _internal_starGiftUpgradePreview(account: Account, giftId: Int64) -> Signal
|
||||
}
|
||||
}
|
||||
|
||||
private final class CachedProfileGifts: Codable {
|
||||
final class CachedProfileGifts: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case gifts
|
||||
case count
|
||||
@ -1118,9 +1162,16 @@ private final class CachedProfileGifts: Codable {
|
||||
}
|
||||
}
|
||||
|
||||
private func entryId(peerId: EnginePeer.Id) -> ItemCacheEntryId {
|
||||
let cacheKey = ValueBoxKey(length: 8)
|
||||
cacheKey.setInt64(0, value: peerId.toInt64())
|
||||
func giftsEntryId(peerId: EnginePeer.Id, collectionId: Int32?) -> ItemCacheEntryId {
|
||||
let cacheKey: ValueBoxKey
|
||||
if let collectionId {
|
||||
cacheKey = ValueBoxKey(length: 8 + 4)
|
||||
cacheKey.setInt64(0, value: peerId.toInt64())
|
||||
cacheKey.setInt32(8, value: collectionId)
|
||||
} else {
|
||||
cacheKey = ValueBoxKey(length: 8)
|
||||
cacheKey.setInt64(0, value: peerId.toInt64())
|
||||
}
|
||||
return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedProfileGifts, key: cacheKey)
|
||||
}
|
||||
|
||||
@ -1128,6 +1179,7 @@ private final class ProfileGiftsContextImpl {
|
||||
private let queue: Queue
|
||||
private let account: Account
|
||||
private let peerId: PeerId
|
||||
private let collectionId: Int32?
|
||||
|
||||
private let disposable = MetaDisposable()
|
||||
private let cacheDisposable = MetaDisposable()
|
||||
@ -1156,12 +1208,14 @@ private final class ProfileGiftsContextImpl {
|
||||
queue: Queue,
|
||||
account: Account,
|
||||
peerId: EnginePeer.Id,
|
||||
collectionId: Int32?,
|
||||
sorting: ProfileGiftsContext.Sorting,
|
||||
filter: ProfileGiftsContext.Filters
|
||||
) {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.peerId = peerId
|
||||
self.collectionId = collectionId
|
||||
self.sorting = sorting
|
||||
self.filter = filter
|
||||
|
||||
@ -1182,6 +1236,7 @@ private final class ProfileGiftsContextImpl {
|
||||
|
||||
func loadMore(reload: Bool = false) {
|
||||
let peerId = self.peerId
|
||||
let collectionId = self.collectionId
|
||||
let accountPeerId = self.account.peerId
|
||||
let network = self.account.network
|
||||
let postbox = self.account.postbox
|
||||
@ -1200,7 +1255,7 @@ private final class ProfileGiftsContextImpl {
|
||||
if case let .ready(true, initialNextOffset) = dataState {
|
||||
if !isFiltered || isUniqueOnlyFilter, self.gifts.isEmpty, initialNextOffset == nil, !reload {
|
||||
self.cacheDisposable.set((self.account.postbox.transaction { transaction -> CachedProfileGifts? in
|
||||
let cachedGifts = transaction.retrieveItemCacheEntry(id: entryId(peerId: peerId))?.get(CachedProfileGifts.self)
|
||||
let cachedGifts = transaction.retrieveItemCacheEntry(id: giftsEntryId(peerId: peerId, collectionId: collectionId))?.get(CachedProfileGifts.self)
|
||||
cachedGifts?.render(transaction: transaction)
|
||||
return cachedGifts
|
||||
} |> deliverOn(self.queue)).start(next: { [weak self] cachedGifts in
|
||||
@ -1248,6 +1303,9 @@ private final class ProfileGiftsContextImpl {
|
||||
return .single(([], 0, nil, nil))
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
if let _ = collectionId {
|
||||
flags |= (1 << 6)
|
||||
}
|
||||
if case .value = sorting {
|
||||
flags |= (1 << 5)
|
||||
}
|
||||
@ -1266,7 +1324,7 @@ private final class ProfileGiftsContextImpl {
|
||||
if !filter.contains(.unique) {
|
||||
flags |= (1 << 4)
|
||||
}
|
||||
return network.request(Api.functions.payments.getSavedStarGifts(flags: flags, peer: inputPeer, offset: initialNextOffset ?? "", limit: 36))
|
||||
return network.request(Api.functions.payments.getSavedStarGifts(flags: flags, peer: inputPeer, collectionId: collectionId, offset: initialNextOffset ?? "", limit: 36))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.payments.SavedStarGifts?, NoError> in
|
||||
return .single(nil)
|
||||
@ -1319,7 +1377,7 @@ private final class ProfileGiftsContextImpl {
|
||||
self.gifts = gifts
|
||||
self.cacheDisposable.set(self.account.postbox.transaction { transaction in
|
||||
if let entry = CodableEntry(CachedProfileGifts(gifts: gifts, count: count, notificationsEnabled: notificationsEnabled)) {
|
||||
transaction.putItemCacheEntry(id: entryId(peerId: peerId), entry: entry)
|
||||
transaction.putItemCacheEntry(id: giftsEntryId(peerId: peerId, collectionId: collectionId), entry: entry)
|
||||
}
|
||||
}.start())
|
||||
} else {
|
||||
@ -1590,6 +1648,88 @@ private final class ProfileGiftsContextImpl {
|
||||
self.pushState()
|
||||
}
|
||||
|
||||
func insertStarGifts(gifts: [ProfileGiftsContext.State.StarGift]) {
|
||||
self.gifts.insert(contentsOf: gifts, at: 0)
|
||||
self.pushState()
|
||||
|
||||
let peerId = self.peerId
|
||||
let collectionId = self.collectionId
|
||||
self.cacheDisposable.set(self.account.postbox.transaction { transaction in
|
||||
var updatedGifts: [ProfileGiftsContext.State.StarGift] = []
|
||||
var updatedCount: Int32 = 0
|
||||
if let cachedGifts = transaction.retrieveItemCacheEntry(id: giftsEntryId(peerId: peerId, collectionId: collectionId))?.get(CachedProfileGifts.self) {
|
||||
updatedGifts = cachedGifts.gifts
|
||||
updatedCount = cachedGifts.count
|
||||
} else {
|
||||
updatedGifts = []
|
||||
}
|
||||
updatedGifts.insert(contentsOf: gifts, at: 0)
|
||||
updatedCount += Int32(gifts.count)
|
||||
if let entry = CodableEntry(CachedProfileGifts(gifts: updatedGifts, count: updatedCount, notificationsEnabled: nil)) {
|
||||
transaction.putItemCacheEntry(id: giftsEntryId(peerId: peerId, collectionId: collectionId), entry: entry)
|
||||
}
|
||||
}.start())
|
||||
}
|
||||
|
||||
func removeStarGifts(references: [StarGiftReference]) {
|
||||
self.gifts.removeAll(where: {
|
||||
if let reference = $0.reference {
|
||||
return references.contains(reference)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
})
|
||||
self.pushState()
|
||||
|
||||
let peerId = self.peerId
|
||||
let collectionId = self.collectionId
|
||||
self.cacheDisposable.set(self.account.postbox.transaction { transaction in
|
||||
var updatedGifts: [ProfileGiftsContext.State.StarGift] = []
|
||||
var updatedCount: Int32 = 0
|
||||
if let cachedGifts = transaction.retrieveItemCacheEntry(id: giftsEntryId(peerId: peerId, collectionId: collectionId))?.get(CachedProfileGifts.self) {
|
||||
updatedGifts = cachedGifts.gifts
|
||||
updatedCount = cachedGifts.count
|
||||
} else {
|
||||
updatedGifts = []
|
||||
}
|
||||
updatedGifts = updatedGifts.filter { gift in
|
||||
if let reference = gift.reference {
|
||||
return !references.contains(reference)
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
updatedCount -= Int32(references.count)
|
||||
if let entry = CodableEntry(CachedProfileGifts(gifts: updatedGifts, count: updatedCount, notificationsEnabled: nil)) {
|
||||
transaction.putItemCacheEntry(id: giftsEntryId(peerId: peerId, collectionId: collectionId), entry: entry)
|
||||
}
|
||||
}.start())
|
||||
}
|
||||
|
||||
func reorderStarGifts(references: [StarGiftReference]) {
|
||||
let giftsSet = Set(references)
|
||||
var giftsMap: [StarGiftReference: ProfileGiftsContext.State.StarGift] = [:]
|
||||
for gift in self.gifts {
|
||||
if let reference = gift.reference {
|
||||
giftsMap[reference] = gift
|
||||
}
|
||||
}
|
||||
var updatedGifts: [ProfileGiftsContext.State.StarGift] = []
|
||||
for reference in references {
|
||||
if let gift = giftsMap[reference] {
|
||||
updatedGifts.append(gift)
|
||||
}
|
||||
}
|
||||
for gift in self.gifts {
|
||||
if let reference = gift.reference, giftsSet.contains(reference) {
|
||||
continue
|
||||
}
|
||||
updatedGifts.append(gift)
|
||||
}
|
||||
self.gifts = updatedGifts
|
||||
self.pushState()
|
||||
}
|
||||
|
||||
func upgradeStarGift(formId: Int64?, reference: StarGiftReference, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
guard let self else {
|
||||
@ -2016,15 +2156,22 @@ public final class ProfileGiftsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public let peerId: EnginePeer.Id
|
||||
public let collectionId: Int32?
|
||||
|
||||
public init(
|
||||
account: Account,
|
||||
peerId: EnginePeer.Id,
|
||||
collectionId: Int32? = nil,
|
||||
sorting: ProfileGiftsContext.Sorting = .date,
|
||||
filter: ProfileGiftsContext.Filters = .All
|
||||
) {
|
||||
self.peerId = peerId
|
||||
self.collectionId = collectionId
|
||||
|
||||
let queue = self.queue
|
||||
self.impl = QueueLocalObject(queue: queue, generate: {
|
||||
return ProfileGiftsContextImpl(queue: queue, account: account, peerId: peerId, sorting: sorting, filter: filter)
|
||||
return ProfileGiftsContextImpl(queue: queue, account: account, peerId: peerId, collectionId: collectionId, sorting: sorting, filter: filter)
|
||||
})
|
||||
}
|
||||
|
||||
@ -2084,6 +2231,24 @@ public final class ProfileGiftsContext {
|
||||
}
|
||||
}
|
||||
|
||||
public func insertStarGifts(gifts: [ProfileGiftsContext.State.StarGift]) {
|
||||
self.impl.with { impl in
|
||||
impl.insertStarGifts(gifts: gifts)
|
||||
}
|
||||
}
|
||||
|
||||
public func removeStarGifts(references: [StarGiftReference]) {
|
||||
self.impl.with { impl in
|
||||
impl.removeStarGifts(references: references)
|
||||
}
|
||||
}
|
||||
|
||||
public func reorderStarGifts(references: [StarGiftReference]) {
|
||||
self.impl.with { impl in
|
||||
impl.reorderStarGifts(references: references)
|
||||
}
|
||||
}
|
||||
|
||||
public func transferStarGift(prepaid: Bool, reference: StarGiftReference, peerId: EnginePeer.Id) -> Signal<Never, TransferStarGiftError> {
|
||||
return Signal { subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
@ -0,0 +1,436 @@
|
||||
import Foundation
|
||||
import Postbox
|
||||
import MtProtoKit
|
||||
import SwiftSignalKit
|
||||
import TelegramApi
|
||||
|
||||
public struct StarGiftCollection: Codable, Equatable {
|
||||
public let id: Int32
|
||||
public let title: String
|
||||
public let icon: TelegramMediaFile?
|
||||
public let count: Int32
|
||||
public let hash: Int64
|
||||
|
||||
public init(id: Int32, title: String, icon: TelegramMediaFile?, count: Int32, hash: Int64) {
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.icon = icon
|
||||
self.count = count
|
||||
self.hash = hash
|
||||
}
|
||||
|
||||
public static func ==(lhs: StarGiftCollection, rhs: StarGiftCollection) -> Bool {
|
||||
if lhs.id != rhs.id {
|
||||
return false
|
||||
}
|
||||
if lhs.title != rhs.title {
|
||||
return false
|
||||
}
|
||||
if lhs.icon != rhs.icon {
|
||||
return false
|
||||
}
|
||||
if lhs.count != rhs.count {
|
||||
return false
|
||||
}
|
||||
if lhs.hash != rhs.hash {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension StarGiftCollection {
|
||||
init?(apiStarGiftCollection: Api.StarGiftCollection) {
|
||||
switch apiStarGiftCollection {
|
||||
case let .starGiftCollection(_, collectionId, title, icon, giftsCount, hash):
|
||||
self.id = collectionId
|
||||
self.title = title
|
||||
self.icon = icon.flatMap { telegramMediaFileFromApiDocument($0, altDocuments: nil) }
|
||||
self.count = giftsCount
|
||||
self.hash = hash
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class CachedProfileGiftsCollections: Codable {
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case collections
|
||||
}
|
||||
|
||||
let collections: [StarGiftCollection]
|
||||
|
||||
init(collections: [StarGiftCollection]) {
|
||||
self.collections = collections
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
self.collections = try container.decode([StarGiftCollection].self, forKey: .collections)
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encode(self.collections, forKey: .collections)
|
||||
}
|
||||
}
|
||||
|
||||
private func entryId(peerId: EnginePeer.Id) -> ItemCacheEntryId {
|
||||
let cacheKey = ValueBoxKey(length: 8)
|
||||
cacheKey.setInt64(0, value: peerId.toInt64())
|
||||
return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedProfileGiftsCollections, key: cacheKey)
|
||||
}
|
||||
|
||||
private func intListSimpleHash(_ list: [Int64]) -> Int64 {
|
||||
var acc: Int64 = 0
|
||||
for value in list {
|
||||
acc = ((acc * 20261) + Int64(0x80000000) + Int64(value)) % Int64(0x80000000)
|
||||
}
|
||||
return Int64(Int32(truncatingIfNeeded: acc))
|
||||
}
|
||||
|
||||
private func _internal_getStarGiftCollections(postbox: Postbox, network: Network, peerId: EnginePeer.Id) -> Signal<[StarGiftCollection]?, NoError> {
|
||||
return postbox.transaction { transaction -> (Api.InputPeer, [StarGiftCollection]?)? in
|
||||
guard let inputPeer = transaction.getPeer(peerId).flatMap(apiInputPeer) else {
|
||||
return nil
|
||||
}
|
||||
let collections = transaction.retrieveItemCacheEntry(id: entryId(peerId: peerId))?.get(CachedProfileGiftsCollections.self)
|
||||
return (inputPeer, collections?.collections)
|
||||
}
|
||||
|> mapToSignal { inputPeerAndHash -> Signal<[StarGiftCollection]?, NoError> in
|
||||
guard let (inputPeer, cachedCollections) = inputPeerAndHash else {
|
||||
return .single(nil)
|
||||
}
|
||||
|
||||
var hash: Int64 = 0
|
||||
if let cachedCollections {
|
||||
hash = intListSimpleHash(cachedCollections.map { $0.hash })
|
||||
}
|
||||
|
||||
return network.request(Api.functions.payments.getStarGiftCollections(peer: inputPeer, hash: hash))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.payments.StarGiftCollections?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> mapToSignal { result -> Signal<[StarGiftCollection]?, NoError> in
|
||||
guard let result else {
|
||||
return .single(nil)
|
||||
}
|
||||
return postbox.transaction { transaction -> [StarGiftCollection]? in
|
||||
switch result {
|
||||
case let .starGiftCollections(collections):
|
||||
let collections = collections.compactMap { StarGiftCollection(apiStarGiftCollection: $0) }
|
||||
if let entry = CodableEntry(CachedProfileGiftsCollections(collections: collections)) {
|
||||
transaction.putItemCacheEntry(id: entryId(peerId: peerId), entry: entry)
|
||||
}
|
||||
return collections
|
||||
case .starGiftCollectionsNotModified:
|
||||
return cachedCollections ?? []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func _internal_createStarGiftCollection(account: Account, peerId: EnginePeer.Id, title: String, starGifts: [ProfileGiftsContext.State.StarGift]) -> Signal<StarGiftCollection?, NoError> {
|
||||
return account.postbox.transaction { transaction -> (Api.InputPeer, [Api.InputSavedStarGift])? in
|
||||
guard let inputPeer = transaction.getPeer(peerId).flatMap(apiInputPeer) else {
|
||||
return nil
|
||||
}
|
||||
let inputStarGifts = starGifts.compactMap { $0.reference }.compactMap { $0.apiStarGiftReference(transaction: transaction) }
|
||||
return (inputPeer, inputStarGifts)
|
||||
}
|
||||
|> mapToSignal { inputPeerAndGifts -> Signal<StarGiftCollection?, NoError> in
|
||||
guard let (inputPeer, inputStarGifts) = inputPeerAndGifts else {
|
||||
return .single(nil)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.payments.createStarGiftCollection(peer: inputPeer, title: title, stargift: inputStarGifts))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.StarGiftCollection?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { result -> StarGiftCollection? in
|
||||
guard let result else {
|
||||
return nil
|
||||
}
|
||||
return StarGiftCollection(apiStarGiftCollection: result)
|
||||
}
|
||||
|> beforeNext { collection in
|
||||
let _ = account.postbox.transaction { transaction in
|
||||
if let collection, let entry = CodableEntry(CachedProfileGifts(gifts: starGifts.map { $0.withPinnedToTop(false) }, count: Int32(starGifts.count), notificationsEnabled: nil)) {
|
||||
transaction.putItemCacheEntry(id: giftsEntryId(peerId: peerId, collectionId: collection.id), entry: entry)
|
||||
}
|
||||
}.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func _internal_reorderStarGiftCollections(account: Account, peerId: EnginePeer.Id, order: [Int32]) -> Signal<Bool, NoError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<Bool, NoError> in
|
||||
guard let inputPeer else {
|
||||
return .single(false)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.payments.reorderStarGiftCollections(peer: inputPeer, order: order))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Bool?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { result -> Bool in
|
||||
if let result, case .boolTrue = result {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func _internal_updateStarGiftCollection(account: Account, peerId: EnginePeer.Id, collectionId: Int32, giftsContext: ProfileGiftsContext?, actions: [ProfileGiftsCollectionsContext.UpdateAction]) -> Signal<StarGiftCollection?, NoError> {
|
||||
for action in actions {
|
||||
switch action {
|
||||
case let .addGifts(gifts):
|
||||
giftsContext?.insertStarGifts(gifts: gifts)
|
||||
case let .removeGifts(gifts):
|
||||
giftsContext?.removeStarGifts(references: gifts)
|
||||
case let .reorderGifts(gifts):
|
||||
giftsContext?.reorderStarGifts(references: gifts)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return account.postbox.transaction { transaction -> (Api.InputPeer, (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.StarGiftCollection>))? in
|
||||
guard let inputPeer = transaction.getPeer(peerId).flatMap(apiInputPeer) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
var title: String?
|
||||
var deleteStarGift: [Api.InputSavedStarGift] = []
|
||||
var addStarGift: [Api.InputSavedStarGift] = []
|
||||
var order: [Api.InputSavedStarGift] = []
|
||||
|
||||
for action in actions {
|
||||
switch action {
|
||||
case let .updateTitle(newTitle):
|
||||
flags |= (1 << 0)
|
||||
title = newTitle
|
||||
case let .addGifts(gifts):
|
||||
flags |= (1 << 2)
|
||||
addStarGift.append(contentsOf: gifts.compactMap { $0.reference }.compactMap { $0.apiStarGiftReference(transaction: transaction) })
|
||||
case let .removeGifts(gifts):
|
||||
flags |= (1 << 1)
|
||||
deleteStarGift.append(contentsOf: gifts.compactMap { $0.apiStarGiftReference(transaction: transaction) })
|
||||
case let .reorderGifts(gifts):
|
||||
flags |= (1 << 3)
|
||||
order = gifts.compactMap { $0.apiStarGiftReference(transaction: transaction) }
|
||||
}
|
||||
}
|
||||
|
||||
let request = Api.functions.payments.updateStarGiftCollection(flags: flags, peer: inputPeer, collectionId: collectionId, title: title, deleteStargift: deleteStarGift, addStargift: addStarGift, order: order)
|
||||
|
||||
return (inputPeer, request)
|
||||
}
|
||||
|> mapToSignal { peerAndRequest -> Signal<StarGiftCollection?, NoError> in
|
||||
guard let (_, request) = peerAndRequest else {
|
||||
return .single(nil)
|
||||
}
|
||||
|
||||
return account.network.request(request)
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.StarGiftCollection?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { result -> StarGiftCollection? in
|
||||
guard let result else {
|
||||
return nil
|
||||
}
|
||||
return StarGiftCollection(apiStarGiftCollection: result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func _internal_deleteStarGiftCollection(account: Account, peerId: EnginePeer.Id, collectionId: Int32) -> Signal<Bool, NoError> {
|
||||
return account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<Bool, NoError> in
|
||||
guard let inputPeer else {
|
||||
return .single(false)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.payments.deleteStarGiftCollection(peer: inputPeer, collectionId: collectionId))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.Bool?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
|> map { result -> Bool in
|
||||
if let result, case .boolTrue = result {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class ProfileGiftsCollectionsContext {
|
||||
public struct State: Equatable {
|
||||
public var collections: [StarGiftCollection]
|
||||
public var isLoading: Bool
|
||||
}
|
||||
|
||||
public enum UpdateAction {
|
||||
case updateTitle(String)
|
||||
case addGifts([ProfileGiftsContext.State.StarGift])
|
||||
case removeGifts([StarGiftReference])
|
||||
case reorderGifts([StarGiftReference])
|
||||
}
|
||||
|
||||
private let queue: Queue = .mainQueue()
|
||||
private let account: Account
|
||||
private let peerId: EnginePeer.Id
|
||||
|
||||
private let disposable = MetaDisposable()
|
||||
|
||||
private var collections: [StarGiftCollection] = []
|
||||
private var giftsContexts: [Int32: ProfileGiftsContext] = [:]
|
||||
private var isLoading: Bool = false
|
||||
|
||||
private let stateValue = Promise<State>()
|
||||
public var state: Signal<State, NoError> {
|
||||
return self.stateValue.get()
|
||||
}
|
||||
|
||||
public init(account: Account, peerId: EnginePeer.Id) {
|
||||
self.account = account
|
||||
self.peerId = peerId
|
||||
|
||||
self.reload()
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposable.dispose()
|
||||
}
|
||||
|
||||
public func giftsContextForCollection(id: Int32) -> ProfileGiftsContext {
|
||||
if let current = self.giftsContexts[id] {
|
||||
return current
|
||||
} else {
|
||||
let giftsContext = ProfileGiftsContext(account: self.account, peerId: self.peerId, collectionId: id)
|
||||
self.giftsContexts[id] = giftsContext
|
||||
return giftsContext
|
||||
}
|
||||
}
|
||||
|
||||
public func reload() {
|
||||
guard !self.isLoading else { return }
|
||||
|
||||
self.isLoading = true
|
||||
self.pushState()
|
||||
|
||||
self.disposable.set((_internal_getStarGiftCollections(postbox: self.account.postbox, network: self.account.network, peerId: self.peerId)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] collections in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.collections = collections ?? []
|
||||
self.isLoading = false
|
||||
self.pushState()
|
||||
}))
|
||||
}
|
||||
|
||||
public func createCollection(title: String, starGifts: [ProfileGiftsContext.State.StarGift]) -> Signal<StarGiftCollection?, NoError> {
|
||||
return _internal_createStarGiftCollection(account: self.account, peerId: self.peerId, title: title, starGifts: starGifts)
|
||||
|> deliverOn(self.queue)
|
||||
|> beforeNext { [weak self] collection in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let collection {
|
||||
self.collections.append(collection)
|
||||
self.pushState()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func updateCollection(id: Int32, actions: [UpdateAction]) -> Signal<StarGiftCollection?, NoError> {
|
||||
let giftsContext = self.giftsContextForCollection(id: id)
|
||||
return _internal_updateStarGiftCollection(account: self.account, peerId: self.peerId, collectionId: id, giftsContext: giftsContext, actions: actions)
|
||||
|> deliverOn(self.queue)
|
||||
|> afterNext { [weak self] collection in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
if let collection {
|
||||
if let index = self.collections.firstIndex(where: { $0.id == id }) {
|
||||
self.collections[index] = collection
|
||||
self.pushState()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func addGifts(id: Int32, gifts: [ProfileGiftsContext.State.StarGift]) -> Signal<StarGiftCollection?, NoError> {
|
||||
return self.updateCollection(id: id, actions: [.addGifts(gifts)])
|
||||
}
|
||||
|
||||
public func removeGifts(id: Int32, gifts: [StarGiftReference]) -> Signal<StarGiftCollection?, NoError> {
|
||||
return self.updateCollection(id: id, actions: [.removeGifts(gifts)])
|
||||
}
|
||||
|
||||
public func reorderGifts(id: Int32, gifts: [StarGiftReference]) -> Signal<StarGiftCollection?, NoError> {
|
||||
return self.updateCollection(id: id, actions: [.reorderGifts(gifts)])
|
||||
}
|
||||
|
||||
public func renameCollection(id: Int32, title: String) -> Signal<StarGiftCollection?, NoError> {
|
||||
return self.updateCollection(id: id, actions: [.updateTitle(title)])
|
||||
}
|
||||
|
||||
public func reorderCollections(order: [Int32]) -> Signal<Bool, NoError> {
|
||||
return _internal_reorderStarGiftCollections(account: self.account, peerId: self.peerId, order: order)
|
||||
|> deliverOn(self.queue)
|
||||
|> afterNext { [weak self] collection in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
var collectionMap: [Int32: StarGiftCollection] = [:]
|
||||
for collection in self.collections {
|
||||
collectionMap[collection.id] = collection
|
||||
}
|
||||
var collections: [StarGiftCollection] = []
|
||||
for id in order {
|
||||
if let collection = collectionMap[id] {
|
||||
collections.append(collection)
|
||||
}
|
||||
}
|
||||
self.collections = collections
|
||||
self.pushState()
|
||||
}
|
||||
}
|
||||
|
||||
public func deleteCollection(id: Int32) -> Signal<Bool, NoError> {
|
||||
return _internal_deleteStarGiftCollection(account: self.account, peerId: self.peerId, collectionId: id)
|
||||
|> deliverOn(self.queue)
|
||||
|> afterNext { [weak self] _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.giftsContexts.removeValue(forKey: id)
|
||||
self.collections.removeAll(where: { $0.id == id })
|
||||
self.pushState()
|
||||
}
|
||||
}
|
||||
|
||||
private func pushState() {
|
||||
let state = State(
|
||||
collections: self.collections,
|
||||
isLoading: self.isLoading
|
||||
)
|
||||
self.stateValue.set(.single(state))
|
||||
}
|
||||
}
|
||||
@ -383,7 +383,7 @@ public final class ButtonComponent: Component {
|
||||
isEnabled: Bool,
|
||||
tintWhenDisabled: Bool = true,
|
||||
allowActionWhenDisabled: Bool = false,
|
||||
displaysProgress: Bool,
|
||||
displaysProgress: Bool = false,
|
||||
action: @escaping () -> Void
|
||||
) {
|
||||
self.background = background
|
||||
|
||||
@ -1140,6 +1140,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
var replyMessage: Message?
|
||||
var replyForward: QuotedReplyMessageAttribute?
|
||||
var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)?
|
||||
var replyTodoItemId: Int32?
|
||||
var replyStory: StoryId?
|
||||
for attribute in item.message.attributes {
|
||||
if let attribute = attribute as? InlineBotMessageAttribute {
|
||||
@ -1167,6 +1168,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
|
||||
}
|
||||
replyQuote = replyAttribute.quote.flatMap { ($0, replyAttribute.isQuote) }
|
||||
replyTodoItemId = replyAttribute.todoItemId
|
||||
} else if let quoteReplyAttribute = attribute as? QuotedReplyMessageAttribute {
|
||||
replyForward = quoteReplyAttribute
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
@ -1206,6 +1208,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
message: replyMessage,
|
||||
replyForward: replyForward,
|
||||
quote: replyQuote,
|
||||
todoItemId: replyTodoItemId,
|
||||
story: replyStory,
|
||||
parentMessage: item.message,
|
||||
constrainedSize: CGSize(width: availableContentWidth, height: CGFloat.greatestFiniteMagnitude),
|
||||
|
||||
@ -1926,6 +1926,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
var replyMessage: Message?
|
||||
var replyForward: QuotedReplyMessageAttribute?
|
||||
var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)?
|
||||
var replyTodoItemId: Int32?
|
||||
var replyStory: StoryId?
|
||||
var replyMarkup: ReplyMarkupMessageAttribute?
|
||||
var authorNameColor: UIColor?
|
||||
@ -1943,6 +1944,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
replyMessage = firstMessage.associatedMessages[attribute.messageId]
|
||||
}
|
||||
replyQuote = attribute.quote.flatMap { ($0, attribute.isQuote) }
|
||||
replyTodoItemId = attribute.todoItemId
|
||||
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||
replyForward = attribute
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
@ -2713,6 +2715,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
message: replyMessage,
|
||||
replyForward: replyForward,
|
||||
quote: replyQuote,
|
||||
todoItemId: replyTodoItemId,
|
||||
story: replyStory,
|
||||
parentMessage: item.message,
|
||||
constrainedSize: CGSize(width: maximumNodeWidth - layoutConstants.text.bubbleInsets.left - layoutConstants.text.bubbleInsets.right - 6.0, height: CGFloat.greatestFiniteMagnitude),
|
||||
@ -5195,7 +5198,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
||||
if let replyInfoNode = self.replyInfoNode {
|
||||
progress = replyInfoNode.makeProgress()
|
||||
}
|
||||
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote.flatMap { quote in NavigateToMessageParams.Quote(string: quote.text, offset: quote.offset) } : nil, progress: progress))
|
||||
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.isQuote ? attribute.quote.flatMap { quote in NavigateToMessageParams.Quote(string: quote.text, offset: quote.offset) } : nil, todoTaskId: attribute.todoItemId, progress: progress))
|
||||
}, contextMenuOnLongPress: true))
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
return .action(InternalBubbleTapAction.Action({
|
||||
|
||||
@ -464,6 +464,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, ASGestureReco
|
||||
var replyMessage: Message?
|
||||
var replyForward: QuotedReplyMessageAttribute?
|
||||
var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)?
|
||||
var replyTodoItemId: Int32?
|
||||
var replyStory: StoryId?
|
||||
for attribute in item.message.attributes {
|
||||
if let attribute = attribute as? InlineBotMessageAttribute {
|
||||
@ -507,6 +508,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, ASGestureReco
|
||||
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
|
||||
}
|
||||
replyQuote = replyAttribute.quote.flatMap { ($0, replyAttribute.isQuote) }
|
||||
replyTodoItemId = replyAttribute.todoItemId
|
||||
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||
replyForward = attribute
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
@ -526,6 +528,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, ASGestureReco
|
||||
message: replyMessage,
|
||||
replyForward: replyForward,
|
||||
quote: replyQuote,
|
||||
todoItemId: replyTodoItemId,
|
||||
story: replyStory,
|
||||
parentMessage: item.message,
|
||||
constrainedSize: CGSize(width: max(0, availableWidth), height: CGFloat.greatestFiniteMagnitude),
|
||||
|
||||
@ -352,6 +352,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
var replyMessage: Message?
|
||||
var replyForward: QuotedReplyMessageAttribute?
|
||||
var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)?
|
||||
var replyTodoItemId: Int32?
|
||||
var replyStory: StoryId?
|
||||
|
||||
for attribute in item.message.attributes {
|
||||
@ -382,6 +383,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
|
||||
}
|
||||
replyQuote = replyAttribute.quote.flatMap { ($0, replyAttribute.isQuote) }
|
||||
replyTodoItemId = replyAttribute.todoItemId
|
||||
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||
replyForward = attribute
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
@ -400,6 +402,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
message: replyMessage,
|
||||
replyForward: replyForward,
|
||||
quote: replyQuote,
|
||||
todoItemId: replyTodoItemId,
|
||||
story: replyStory,
|
||||
parentMessage: item.message,
|
||||
constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude),
|
||||
|
||||
@ -22,6 +22,7 @@ swift_library(
|
||||
"//submodules/TelegramStringFormatting",
|
||||
"//submodules/TextFormat",
|
||||
"//submodules/InvisibleInkDustNode",
|
||||
"//submodules/CheckNode",
|
||||
"//submodules/TelegramUI/Components/TextNodeWithEntities",
|
||||
"//submodules/TelegramUI/Components/AnimationCache",
|
||||
"//submodules/TelegramUI/Components/MultiAnimationRenderer",
|
||||
|
||||
@ -17,6 +17,7 @@ import AnimationCache
|
||||
import MultiAnimationRenderer
|
||||
import ChatMessageItemCommon
|
||||
import MessageInlineBlockBackgroundView
|
||||
import CheckNode
|
||||
|
||||
public enum ChatMessageReplyInfoType {
|
||||
case bubble(incoming: Bool)
|
||||
@ -81,6 +82,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
public let message: Message?
|
||||
public let replyForward: QuotedReplyMessageAttribute?
|
||||
public let quote: (quote: EngineMessageReplyQuote, isQuote: Bool)?
|
||||
public let todoItemId: Int32?
|
||||
public let story: StoryId?
|
||||
public let parentMessage: Message
|
||||
public let constrainedSize: CGSize
|
||||
@ -96,6 +98,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
message: Message?,
|
||||
replyForward: QuotedReplyMessageAttribute?,
|
||||
quote: (quote: EngineMessageReplyQuote, isQuote: Bool)?,
|
||||
todoItemId: Int32?,
|
||||
story: StoryId?,
|
||||
parentMessage: Message,
|
||||
constrainedSize: CGSize,
|
||||
@ -110,6 +113,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
self.message = message
|
||||
self.replyForward = replyForward
|
||||
self.quote = quote
|
||||
self.todoItemId = todoItemId
|
||||
self.story = story
|
||||
self.parentMessage = parentMessage
|
||||
self.constrainedSize = constrainedSize
|
||||
@ -136,6 +140,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
private var imageNode: TransformImageNode?
|
||||
private var previousMediaReference: AnyMediaReference?
|
||||
private var expiredStoryIconView: UIImageView?
|
||||
private var checkLayer: CheckLayer?
|
||||
|
||||
private var currentProgressDisposable: Disposable?
|
||||
|
||||
@ -417,8 +422,15 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
textColor = titleColor
|
||||
}
|
||||
|
||||
var textLeftInset: CGFloat = 0.0
|
||||
let messageText: NSAttributedString
|
||||
if isText, let message = arguments.message {
|
||||
var todoItemCompleted: Bool?
|
||||
if let todoItemId = arguments.todoItemId, let todo = arguments.message?.media.first(where: { $0 is TelegramMediaTodo }) as? TelegramMediaTodo, let todoItem = todo.items.first(where: { $0.id == todoItemId }) {
|
||||
messageText = stringWithAppliedEntities(todoItem.text, entities: todoItem.entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: nil)
|
||||
textLeftInset += 16.0
|
||||
|
||||
todoItemCompleted = todo.completions.contains(where: { $0.id == todoItemId })
|
||||
} else if isText, let message = arguments.message {
|
||||
var text: String
|
||||
var messageEntities: [MessageTextEntity]
|
||||
|
||||
@ -577,6 +589,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
textCutoutWidth = imageTextInset + 6.0
|
||||
}
|
||||
}
|
||||
adjustedConstrainedTextSize.width -= textLeftInset
|
||||
|
||||
let (titleLayout, titleApply) = titleNodeLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: maxTitleNumberOfLines, truncationType: .end, constrainedSize: CGSize(width: contrainedTextSize.width - additionalTitleWidth, height: contrainedTextSize.height), alignment: .natural, cutout: nil, insets: textInsets))
|
||||
if isExpiredStory || isStory {
|
||||
@ -643,7 +656,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
var size = CGSize()
|
||||
size.width = max(titleLayout.size.width + additionalTitleWidth - textInsets.left - textInsets.right, textLayout.size.width - textInsets.left - textInsets.right - textCutoutWidth) + leftInset + 6.0
|
||||
size.width = max(titleLayout.size.width + additionalTitleWidth - textInsets.left - textInsets.right, textLeftInset + textLayout.size.width - textInsets.left - textInsets.right - textCutoutWidth) + leftInset + 6.0
|
||||
size.height = titleLayout.size.height + textLayout.size.height - 2 * (textInsets.top + textInsets.bottom) + 2 * spacing
|
||||
size.height += 2.0
|
||||
if isExpiredStory || isStory {
|
||||
@ -713,7 +726,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
|
||||
titleNode.frame = CGRect(origin: CGPoint(x: leftInset - textInsets.left - 2.0, y: spacing - textInsets.top + 1.0), size: titleLayout.size)
|
||||
|
||||
let textFrame = CGRect(origin: CGPoint(x: leftInset - textInsets.left - 2.0 - textCutoutWidth, y: titleNode.frame.maxY - textInsets.bottom + spacing - textInsets.top - 2.0), size: textLayout.size)
|
||||
let textFrame = CGRect(origin: CGPoint(x: textLeftInset + leftInset - textInsets.left - 2.0 - textCutoutWidth, y: titleNode.frame.maxY - textInsets.bottom + spacing - textInsets.top - 2.0), size: textLayout.size)
|
||||
let effectiveTextFrame = textFrame.offsetBy(dx: (isExpiredStory || isStory) ? 18.0 : 0.0, dy: 0.0)
|
||||
|
||||
if textNode.textNode.bounds.isEmpty || !animation.isAnimated || textNode.textNode.bounds.height == effectiveTextFrame.height {
|
||||
@ -841,11 +854,33 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
||||
quoteIconView.frame = quoteIconFrame
|
||||
}
|
||||
quoteIconView.tintColor = mainColor
|
||||
} else {
|
||||
if let quoteIconView = node.quoteIconView {
|
||||
node.quoteIconView = nil
|
||||
quoteIconView.removeFromSuperview()
|
||||
} else if let quoteIconView = node.quoteIconView {
|
||||
node.quoteIconView = nil
|
||||
quoteIconView.removeFromSuperview()
|
||||
}
|
||||
|
||||
if let todoItemCompleted {
|
||||
let checkLayerFrame = CGRect(origin: CGPoint(x: textFrame.minX - 16.0, y: textFrame.minY + 5.0), size: CGSize(width: 12.0, height: 12.0))
|
||||
let checkTheme = CheckNodeTheme(backgroundColor: titleColor, strokeColor: .clear, borderColor: titleColor, overlayBorder: false, hasInset: true, hasShadow: false, borderWidth: 1.0)
|
||||
|
||||
let checkLayer: CheckLayer
|
||||
if let current = node.checkLayer {
|
||||
checkLayer = current
|
||||
|
||||
checkLayer.setSelected(todoItemCompleted, animated: true)
|
||||
animation.animator.updateFrame(layer: checkLayer, frame: checkLayerFrame, completion: nil)
|
||||
} else {
|
||||
checkLayer = CheckLayer(theme: checkTheme)
|
||||
node.checkLayer = checkLayer
|
||||
node.contentNode.layer.addSublayer(checkLayer)
|
||||
|
||||
checkLayer.setSelected(todoItemCompleted, animated: false)
|
||||
checkLayer.frame = checkLayerFrame
|
||||
}
|
||||
checkLayer.theme = checkTheme
|
||||
} else if let checkLayer = node.checkLayer {
|
||||
node.checkLayer = nil
|
||||
checkLayer.removeFromSuperlayer()
|
||||
}
|
||||
|
||||
node.contentNode.frame = CGRect(origin: CGPoint(), size: size)
|
||||
|
||||
@ -705,6 +705,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
var replyMessage: Message?
|
||||
var replyForward: QuotedReplyMessageAttribute?
|
||||
var replyQuote: (quote: EngineMessageReplyQuote, isQuote: Bool)?
|
||||
var replyTodoItemId: Int32?
|
||||
var replyStory: StoryId?
|
||||
for attribute in item.message.attributes {
|
||||
if let attribute = attribute as? InlineBotMessageAttribute {
|
||||
@ -733,6 +734,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
|
||||
}
|
||||
replyQuote = replyAttribute.quote.flatMap { ($0, replyAttribute.isQuote) }
|
||||
replyTodoItemId = replyAttribute.todoItemId
|
||||
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||
replyForward = attribute
|
||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||
@ -772,6 +774,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
message: replyMessage,
|
||||
replyForward: replyForward,
|
||||
quote: replyQuote,
|
||||
todoItemId: replyTodoItemId,
|
||||
story: replyStory,
|
||||
parentMessage: item.message,
|
||||
constrainedSize: CGSize(width: availableWidth, height: CGFloat.greatestFiniteMagnitude),
|
||||
|
||||
@ -413,7 +413,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
|
||||
if item.associatedData.isSuspiciousPeer, let entities = messageEntities {
|
||||
if incoming && item.associatedData.isSuspiciousPeer, let entities = messageEntities {
|
||||
messageEntities = entities.filter { entity in
|
||||
switch entity.type {
|
||||
case .Url, .TextUrl, .Mention, .TextMention, .Hashtag, .Email, .BankCard:
|
||||
|
||||
@ -55,7 +55,7 @@ public final class ChatRecentActionsController: TelegramBaseController {
|
||||
|
||||
self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style
|
||||
|
||||
self.panelInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
|
||||
self.panelInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _, _ in
|
||||
}, setupEditMessage: { _, _ in
|
||||
}, beginMessageSelection: { _, _ in
|
||||
}, cancelMessageSelection: { _ in
|
||||
|
||||
@ -53,7 +53,7 @@ private final class FactCheckAlertContentNode: AlertContentNode {
|
||||
return self.isUserInteractionEnabled
|
||||
}
|
||||
|
||||
init(context: AccountContext, theme: AlertControllerTheme, presentationTheme: PresentationTheme, strings: PresentationStrings, actions: [TextAlertAction], text: String, value: String, entities: [MessageTextEntity], characterLimit: Int) {
|
||||
init(context: AccountContext, theme: AlertControllerTheme, presentationTheme: PresentationTheme, strings: PresentationStrings, actions: [TextAlertAction], text: String, value: String, entities: [MessageTextEntity]) {
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
self.presentationTheme = presentationTheme
|
||||
@ -362,7 +362,7 @@ private final class FactCheckAlertContentNode: AlertContentNode {
|
||||
}
|
||||
}
|
||||
|
||||
public func factCheckAlertController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, value: String, entities: [MessageTextEntity], characterLimit: Int = 1000, apply: @escaping (String, [MessageTextEntity]) -> Void) -> AlertController {
|
||||
public func factCheckAlertController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, value: String, entities: [MessageTextEntity], apply: @escaping (String, [MessageTextEntity]) -> Void) -> AlertController {
|
||||
let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
var dismissImpl: ((Bool) -> Void)?
|
||||
@ -375,7 +375,7 @@ public func factCheckAlertController(context: AccountContext, updatedPresentatio
|
||||
applyImpl?()
|
||||
})]
|
||||
|
||||
let contentNode = FactCheckAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), presentationTheme: presentationData.theme, strings: presentationData.strings, actions: actions, text: presentationData.strings.FactCheck_Title, value: value, entities: entities, characterLimit: characterLimit)
|
||||
let contentNode = FactCheckAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), presentationTheme: presentationData.theme, strings: presentationData.strings, actions: actions, text: presentationData.strings.FactCheck_Title, value: value, entities: entities)
|
||||
contentNode.complete = {
|
||||
applyImpl?()
|
||||
}
|
||||
|
||||
@ -26,6 +26,7 @@ public final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
public let chatPeerId: EnginePeer.Id
|
||||
public let messageId: MessageId
|
||||
public let quote: EngineMessageReplyQuote?
|
||||
public let todoItemId: Int32?
|
||||
|
||||
private var previousMediaReference: AnyMediaReference?
|
||||
|
||||
@ -46,10 +47,11 @@ public final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
|
||||
private var validLayout: (size: CGSize, inset: CGFloat, interfaceState: ChatPresentationInterfaceState)?
|
||||
|
||||
public init(context: AccountContext, chatPeerId: EnginePeer.Id, messageId: MessageId, quote: EngineMessageReplyQuote?, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) {
|
||||
public init(context: AccountContext, chatPeerId: EnginePeer.Id, messageId: MessageId, quote: EngineMessageReplyQuote?, todoItemId: Int32?, theme: PresentationTheme, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, animationCache: AnimationCache?, animationRenderer: MultiAnimationRenderer?) {
|
||||
self.chatPeerId = chatPeerId
|
||||
self.messageId = messageId
|
||||
self.quote = quote
|
||||
self.todoItemId = todoItemId
|
||||
|
||||
self.context = context
|
||||
self.theme = theme
|
||||
@ -116,7 +118,7 @@ public final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
if let strongSelf = self {
|
||||
if messageView.message == nil {
|
||||
Queue.mainQueue().justDispatch {
|
||||
strongSelf.interfaceInteraction?.setupReplyMessage(nil, { _, _ in })
|
||||
strongSelf.interfaceInteraction?.setupReplyMessage(nil, nil, { _, _ in })
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -267,7 +269,10 @@ public final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let _ = strongSelf.quote {
|
||||
if let _ = strongSelf.todoItemId {
|
||||
let string = strongSelf.strings.Chat_ReplyPanel_ReplyToTodoItem
|
||||
titleText = [.text(NSAttributedString(string: string, font: Font.medium(15.0), textColor: strongSelf.theme.chat.inputPanel.panelControlAccentColor))]
|
||||
} else if let _ = strongSelf.quote {
|
||||
let string = strongSelf.strings.Chat_ReplyPanel_ReplyToQuoteBy(authorName).string
|
||||
titleText = [.text(NSAttributedString(string: string, font: Font.medium(15.0), textColor: strongSelf.theme.chat.inputPanel.panelControlAccentColor))]
|
||||
} else {
|
||||
@ -298,6 +303,10 @@ public final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
let quoteText = stringWithAppliedEntities(trimToLineCount(quote.text, lineCount: 1), entities: quote.entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message)
|
||||
|
||||
strongSelf.textNode.attributedText = quoteText
|
||||
} else if let todoItemId = strongSelf.todoItemId, let todo = message?.media.first(where: { $0 is TelegramMediaTodo }) as? TelegramMediaTodo, let todoItem = todo.items.first(where: { $0.id == todoItemId }) {
|
||||
let textColor = strongSelf.theme.chat.inputPanel.primaryTextColor
|
||||
let itemText = stringWithAppliedEntities(trimToLineCount(todoItem.text, lineCount: 1), entities: todoItem.entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: message)
|
||||
strongSelf.textNode.attributedText = itemText
|
||||
}
|
||||
|
||||
strongSelf.titleNode.components = titleText
|
||||
|
||||
@ -237,7 +237,7 @@ final class ComposeTodoScreenComponent: Component {
|
||||
self.reorderingItem = nil
|
||||
for (itemId, itemView) in self.todoItemsSectionContainer.itemViews {
|
||||
if itemId == reorderingItem.id, let view = itemView.contents.view {
|
||||
let viewFrame = view.convert(view.bounds, to: self)
|
||||
let viewFrame = view.convert(view.bounds, to: self.scrollView)
|
||||
let transition = ComponentTransition.spring(duration: 0.3)
|
||||
transition.setPosition(view: reorderingItem.snapshotView, position: viewFrame.center)
|
||||
transition.setAlpha(view: reorderingItem.backgroundView, alpha: 0.0, completion: { _ in
|
||||
@ -260,13 +260,14 @@ final class ComposeTodoScreenComponent: Component {
|
||||
|
||||
snapshotView.center = targetPosition
|
||||
|
||||
let localPoint = self.todoItemsSectionContainer.convert(targetPosition, from: self.scrollView)
|
||||
for (itemId, itemView) in self.todoItemsSectionContainer.itemViews {
|
||||
if itemId == id {
|
||||
continue
|
||||
}
|
||||
if let view = itemView.contents.view {
|
||||
let viewFrame = view.convert(view.bounds, to: self)
|
||||
if viewFrame.contains(targetPosition) {
|
||||
let viewFrame = view.convert(view.bounds, to: self.todoItemsSectionContainer)
|
||||
if viewFrame.contains(localPoint) {
|
||||
if let targetIndex = self.todoItems.firstIndex(where: { AnyHashable($0.id) == itemId }), let reorderingItem = self.todoItems.first(where: { AnyHashable($0.id) == id }) {
|
||||
self.reorderIfPossible(item: reorderingItem, toIndex: targetIndex)
|
||||
}
|
||||
@ -1662,7 +1663,7 @@ public class ComposeTodoScreen: ViewControllerComponentContainer, AttachmentCont
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
if !initialData.canEdit && initialData.existingTodo != nil {
|
||||
self.title = presentationData.strings.CreateTodo_Title
|
||||
self.title = presentationData.strings.CreateTodo_AddTitle
|
||||
} else {
|
||||
self.title = initialData.existingTodo != nil ? presentationData.strings.CreateTodo_EditTitle : presentationData.strings.CreateTodo_Title
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import ItemShimmeringLoadingComponent
|
||||
import AvatarNode
|
||||
import PeerInfoCoverComponent
|
||||
import Markdown
|
||||
import CheckNode
|
||||
|
||||
public final class GiftItemComponent: Component {
|
||||
public enum Subject: Equatable {
|
||||
@ -29,6 +30,7 @@ public final class GiftItemComponent: Component {
|
||||
case blue
|
||||
case purple
|
||||
case green
|
||||
case orange
|
||||
case custom(Int32, Int32)
|
||||
|
||||
func colors(theme: PresentationTheme) -> [UIColor] {
|
||||
@ -67,6 +69,11 @@ public final class GiftItemComponent: Component {
|
||||
UIColor(rgb: 0x4bb121),
|
||||
UIColor(rgb: 0x53d654)
|
||||
]
|
||||
case .orange:
|
||||
return [
|
||||
UIColor(rgb: 0xea8b01),
|
||||
UIColor(rgb: 0xfab625)
|
||||
]
|
||||
case let .custom(topColor, _):
|
||||
return [
|
||||
UIColor(rgb: UInt32(bitPattern: topColor)).withMultiplied(hue: 0.97, saturation: 1.45, brightness: 0.89),
|
||||
@ -100,6 +107,20 @@ public final class GiftItemComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
public enum Outline: Equatable {
|
||||
case orange
|
||||
|
||||
func colors(theme: PresentationTheme) -> [UIColor] {
|
||||
switch self {
|
||||
case .orange:
|
||||
return [
|
||||
UIColor(rgb: 0xfab625),
|
||||
UIColor(rgb: 0xea8b01)
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum Peer: Equatable {
|
||||
case peer(EnginePeer)
|
||||
case anonymous
|
||||
@ -111,6 +132,7 @@ public final class GiftItemComponent: Component {
|
||||
case thumbnail
|
||||
case preview
|
||||
case grid
|
||||
case select
|
||||
}
|
||||
|
||||
let context: AccountContext
|
||||
@ -122,6 +144,7 @@ public final class GiftItemComponent: Component {
|
||||
let subtitle: String?
|
||||
let label: String?
|
||||
let ribbon: Ribbon?
|
||||
let outline: Outline?
|
||||
let resellPrice: Int64?
|
||||
let isLoading: Bool
|
||||
let isHidden: Bool
|
||||
@ -143,6 +166,7 @@ public final class GiftItemComponent: Component {
|
||||
subtitle: String? = nil,
|
||||
label: String? = nil,
|
||||
ribbon: Ribbon? = nil,
|
||||
outline: Outline? = nil,
|
||||
resellPrice: Int64? = nil,
|
||||
isLoading: Bool = false,
|
||||
isHidden: Bool = false,
|
||||
@ -163,6 +187,7 @@ public final class GiftItemComponent: Component {
|
||||
self.subtitle = subtitle
|
||||
self.label = label
|
||||
self.ribbon = ribbon
|
||||
self.outline = outline
|
||||
self.resellPrice = resellPrice
|
||||
self.isLoading = isLoading
|
||||
self.isHidden = isHidden
|
||||
@ -203,6 +228,9 @@ public final class GiftItemComponent: Component {
|
||||
if lhs.ribbon != rhs.ribbon {
|
||||
return false
|
||||
}
|
||||
if lhs.outline != rhs.outline {
|
||||
return false
|
||||
}
|
||||
if lhs.resellPrice != rhs.resellPrice {
|
||||
return false
|
||||
}
|
||||
@ -256,6 +284,8 @@ public final class GiftItemComponent: Component {
|
||||
|
||||
private var animationLayer: InlineStickerItemLayer?
|
||||
private var selectionLayer: SimpleShapeLayer?
|
||||
private var checkLayer: CheckLayer?
|
||||
private var outlineLayer: SimpleLayer?
|
||||
|
||||
private var animationFile: TelegramMediaFile?
|
||||
|
||||
@ -326,7 +356,7 @@ public final class GiftItemComponent: Component {
|
||||
}
|
||||
iconSize = CGSize(width: 88.0, height: 88.0)
|
||||
cornerRadius = 10.0
|
||||
case .profile:
|
||||
case .profile, .select:
|
||||
size = availableSize
|
||||
let side = floor(88.0 * availableSize.height / 116.0)
|
||||
iconSize = CGSize(width: side, height: side)
|
||||
@ -718,7 +748,7 @@ public final class GiftItemComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if let peer = component.peer, !component.isPinned {
|
||||
if let peer = component.peer, !component.isPinned && component.mode != .select {
|
||||
let avatarNode: AvatarNode
|
||||
if let current = self.avatarNode {
|
||||
avatarNode = current
|
||||
@ -854,7 +884,6 @@ public final class GiftItemComponent: Component {
|
||||
})
|
||||
hiddenIcon.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false)
|
||||
}
|
||||
|
||||
|
||||
if let resellPrice = component.resellPrice {
|
||||
let labelColor = UIColor.white
|
||||
@ -965,6 +994,91 @@ public final class GiftItemComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
if case .select = component.mode {
|
||||
var checkFrame = CGRect(origin: CGPoint(x: 4.0, y: 4.0), size: CGSize(width: 26.0, height: 26.0))
|
||||
let checkTheme: CheckNodeTheme
|
||||
if case .uniqueGift = component.subject {
|
||||
checkTheme = CheckNodeTheme(theme: component.theme, style: .overlay)
|
||||
} else {
|
||||
checkTheme = CheckNodeTheme(theme: component.theme, style: .plain)
|
||||
checkFrame = checkFrame.insetBy(dx: 2.0, dy: 2.0)
|
||||
}
|
||||
|
||||
var isAnimated = true
|
||||
let checkLayer: CheckLayer
|
||||
if let current = self.checkLayer {
|
||||
checkLayer = current
|
||||
} else {
|
||||
isAnimated = false
|
||||
checkLayer = CheckLayer(theme: checkTheme)
|
||||
self.checkLayer = checkLayer
|
||||
self.layer.addSublayer(checkLayer)
|
||||
}
|
||||
|
||||
checkLayer.theme = checkTheme
|
||||
checkLayer.frame = checkFrame
|
||||
checkLayer.setSelected(component.isSelected, animated: isAnimated)
|
||||
}
|
||||
|
||||
if let outline = component.outline {
|
||||
let lineWidth: CGFloat = 2.0
|
||||
let outlineFrame = backgroundFrame
|
||||
|
||||
let outlineLayer: SimpleLayer
|
||||
if let current = self.outlineLayer {
|
||||
outlineLayer = current
|
||||
} else {
|
||||
outlineLayer = SimpleLayer()
|
||||
self.outlineLayer = outlineLayer
|
||||
if self.ribbon.layer.superlayer != nil {
|
||||
self.layer.insertSublayer(outlineLayer, below: self.ribbon.layer)
|
||||
} else {
|
||||
self.layer.addSublayer(outlineLayer)
|
||||
}
|
||||
|
||||
let image = generateImage(outlineFrame.size, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: .zero, size: size))
|
||||
|
||||
context.addPath(CGPath(roundedRect: CGRect(origin: .zero, size: outlineFrame.size), cornerWidth: 10.0, cornerHeight: 10.0, transform: nil))
|
||||
context.addPath(CGPath(roundedRect: CGRect(origin: .zero, size: outlineFrame.size).insetBy(dx: lineWidth, dy: lineWidth), cornerWidth: 8.0, cornerHeight: 8.0, transform: nil))
|
||||
|
||||
context.clip(using: .evenOdd)
|
||||
|
||||
var locations: [CGFloat] = [0.0, 1.0]
|
||||
let colors: [CGColor] = outline.colors(theme: component.theme).map { $0.cgColor }
|
||||
|
||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
|
||||
|
||||
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: size.height), options: CGGradientDrawingOptions())
|
||||
|
||||
context.resetClip()
|
||||
|
||||
if let _ = component.ribbon, let ribbonOutline = ribbonOutlineImage, let cgImage = ribbonOutline.cgImage {
|
||||
context.saveGState()
|
||||
|
||||
context.translateBy(x: 0.0, y: size.height)
|
||||
context.scaleBy(x: 1.0, y: -1.0)
|
||||
|
||||
//58
|
||||
context.clip(to: CGRect(origin: CGPoint(x: 68.0, y: 91.0 - UIScreenPixel), size: ribbonOutline.size), mask: cgImage)
|
||||
context.setBlendMode(.clear)
|
||||
context.setFillColor(UIColor.clear.cgColor)
|
||||
context.fill(CGRect(origin: .zero, size: size))
|
||||
|
||||
context.restoreGState()
|
||||
}
|
||||
})
|
||||
outlineLayer.contents = image?.cgImage
|
||||
|
||||
outlineLayer.frame = outlineFrame
|
||||
}
|
||||
|
||||
} else if let outlineLayer = self.outlineLayer {
|
||||
self.outlineLayer = nil
|
||||
outlineLayer.removeFromSuperlayer()
|
||||
}
|
||||
|
||||
if let _ = component.action {
|
||||
self.addSubview(self.containerButton)
|
||||
self.containerButton.isUserInteractionEnabled = true
|
||||
|
||||
@ -369,6 +369,7 @@ final class GiftOptionsScreenComponent: Component {
|
||||
}
|
||||
|
||||
var ribbon: GiftItemComponent.Ribbon?
|
||||
var outline: GiftItemComponent.Outline?
|
||||
var isSoldOut = false
|
||||
switch gift {
|
||||
case let .generic(gift):
|
||||
@ -391,6 +392,14 @@ final class GiftOptionsScreenComponent: Component {
|
||||
color: .blue
|
||||
)
|
||||
}
|
||||
|
||||
if gift.flags.contains(.requiresPremium) {
|
||||
ribbon = GiftItemComponent.Ribbon(
|
||||
text: "premium",
|
||||
color: .orange
|
||||
)
|
||||
outline = .orange
|
||||
}
|
||||
case let .unique(gift):
|
||||
var ribbonColor: GiftItemComponent.Ribbon.Color = .blue
|
||||
for attribute in gift.attributes {
|
||||
@ -435,6 +444,7 @@ final class GiftOptionsScreenComponent: Component {
|
||||
peer: nil,
|
||||
subject: subject,
|
||||
ribbon: ribbon,
|
||||
outline: outline,
|
||||
isSoldOut: isSoldOut
|
||||
)
|
||||
),
|
||||
@ -449,6 +459,19 @@ final class GiftOptionsScreenComponent: Component {
|
||||
mainController = controller
|
||||
}
|
||||
if case let .generic(gift) = gift {
|
||||
if let perUserLimit = gift.perUserLimit, perUserLimit.remains == 0 {
|
||||
//TODO:localize
|
||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = UndoOverlayController(presentationData: presentationData, content: .sticker(context: component.context, file: gift.file, loop: true, title: nil, text: "You've already sent \(perUserLimit.total) of these gifts, and it's the limit.", undoText: nil, customAction: nil), action: { _ in return false })
|
||||
mainController.present(controller, in: .current)
|
||||
return
|
||||
}
|
||||
if gift.flags.contains(.requiresPremium) && !component.context.isPremium {
|
||||
let controller = component.context.sharedContext.makePremiumIntroController(context: component.context, source: .premiumGift(gift.file), forceDark: false, dismissed: nil)
|
||||
mainController.push(controller)
|
||||
return
|
||||
}
|
||||
|
||||
if let availability = gift.availability, availability.remains == 0 {
|
||||
if availability.resale > 0 {
|
||||
let storeController = component.context.sharedContext.makeGiftStoreController(
|
||||
@ -533,8 +556,6 @@ final class GiftOptionsScreenComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var topPanelHeight = environment.navigationHeight
|
||||
let tabSelectorThreshold = self.tabSelectorOrigin - 8.0
|
||||
if contentOffset > tabSelectorThreshold - environment.navigationHeight {
|
||||
|
||||
@ -2368,7 +2368,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
||||
transition: .immediate
|
||||
)
|
||||
context.add(descriptionButton
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: 207.0 + descriptionOffset + description.size.height / 2.0 - UIScreenPixel))
|
||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: 207.0 + descriptionOffset + description.size.height / 2.0 - 1.0))
|
||||
.appear(.default(alpha: true))
|
||||
.disappear(.default(alpha: true))
|
||||
)
|
||||
|
||||
@ -315,7 +315,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
self.selectionPanel = ChatMessageSelectionInputPanelNode(theme: presentationData.theme, strings: presentationData.strings, peerMedia: true)
|
||||
self.selectionPanel.context = context
|
||||
|
||||
let interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
|
||||
let interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _, _ in
|
||||
}, setupEditMessage: { _, _ in
|
||||
}, beginMessageSelection: { _, _ in
|
||||
}, cancelMessageSelection: { _ in
|
||||
|
||||
@ -381,7 +381,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
self.indexChanged(1)
|
||||
}
|
||||
|
||||
self.interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _ in
|
||||
self.interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { _, _, _ in
|
||||
}, setupEditMessage: { _, _ in
|
||||
}, beginMessageSelection: { _, _ in
|
||||
}, cancelMessageSelection: { _ in
|
||||
|
||||
@ -25,7 +25,7 @@ public final class PlainButtonComponent: Component {
|
||||
public init(
|
||||
content: AnyComponent<Empty>,
|
||||
background: AnyComponent<Empty>? = nil,
|
||||
effectAlignment: EffectAlignment,
|
||||
effectAlignment: EffectAlignment = .center,
|
||||
minSize: CGSize? = nil,
|
||||
contentInsets: UIEdgeInsets = UIEdgeInsets(),
|
||||
action: @escaping () -> Void,
|
||||
|
||||
@ -240,7 +240,7 @@ final class PeerNameColorChatPreviewItemNode: ListViewItemNode {
|
||||
media.append(TelegramMediaWebpage(webpageId: MediaId(namespace: 0, id: 0), content: .Loaded(TelegramMediaWebpageLoadedContent(url: "", displayUrl: "", hash: 0, type: nil, websiteName: site, title: title, text: text, embedUrl: nil, embedType: nil, embedSize: nil, duration: nil, author: nil, isMediaLargeByDefault: nil, imageIsVideoCover: false, image: nil, file: nil, story: nil, attributes: [], instantPage: nil))))
|
||||
}
|
||||
|
||||
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message = Message(stableId: 1, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 1), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: messageItem.outgoing ? [] : [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[authorPeerId], text: messageItem.text, attributes: messageItem.reply != nil ? [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)] : [], media: media, peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
items.append(item.context.sharedContext.makeChatMessagePreviewItem(context: item.context, messages: [message], theme: item.componentTheme, strings: item.strings, wallpaper: item.wallpaper, fontSize: item.fontSize, chatBubbleCorners: item.chatBubbleCorners, dateTimeFormat: item.dateTimeFormat, nameOrder: item.nameDisplayOrder, forcedResourceStatus: nil, tapMessage: nil, clickThroughMessage: nil, backgroundNode: currentBackgroundNode, availableReactions: nil, accountPeer: nil, isCentered: false, isPreview: true, isStandalone: false))
|
||||
}
|
||||
|
||||
|
||||
@ -1071,7 +1071,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate
|
||||
messages[message4.id] = message4
|
||||
sampleMessages.append(message4)
|
||||
|
||||
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message5 = Message(stableId: 5, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 5), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66004, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_1_Text, attributes: [ReplyMessageAttribute(messageId: message4.id, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
messages[message5.id] = message5
|
||||
sampleMessages.append(message5)
|
||||
|
||||
@ -1082,7 +1082,7 @@ final class ThemeAccentColorControllerNode: ASDisplayNode, ASScrollViewDelegate
|
||||
let message6 = Message(stableId: 6, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 6), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66005, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: "", attributes: [], media: [voiceMedia], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
sampleMessages.append(message6)
|
||||
|
||||
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
let message7 = Message(stableId: 7, stableVersion: 0, id: MessageId(peerId: peerId, namespace: 0, id: 7), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66006, flags: [.Incoming], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[peerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_2_Text, attributes: [ReplyMessageAttribute(messageId: message5.id, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
sampleMessages.append(message7)
|
||||
|
||||
let message8 = Message(stableId: 8, stableVersion: 0, id: MessageId(peerId: otherPeerId, namespace: 0, id: 8), globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66007, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: peers[otherPeerId], text: self.presentationData.strings.Appearance_ThemePreview_Chat_3_Text, attributes: [], media: [], peers: peers, associatedMessages: messages, associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
|
||||
@ -1524,7 +1524,7 @@ final class WallpaperGalleryItemNode: GalleryItemNode {
|
||||
|
||||
let replyMessageId = MessageId(peerId: peerId, namespace: 0, id: 3)
|
||||
messages[replyMessageId] = Message(stableId: 3, stableVersion: 0, id: replyMessageId, globallyUniqueId: nil, groupingKey: nil, groupInfo: nil, threadId: nil, timestamp: 66000, flags: [], tags: [], globalTags: [], localTags: [], customTags: [], forwardInfo: nil, author: messageAuthor, text: self.presentationData.strings.WallpaperPreview_ChannelReplyText, attributes: [], media: [], peers: peers, associatedMessages: SimpleDictionary(), associatedMessageIds: [], associatedMedia: [:], associatedThreadInfo: nil, associatedStories: [:])
|
||||
messageAttributes = [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false)]
|
||||
messageAttributes = [ReplyMessageAttribute(messageId: replyMessageId, threadMessageId: nil, quote: nil, isQuote: false, todoItemId: nil)]
|
||||
}
|
||||
|
||||
peers[peerId] = messageAuthor
|
||||
|
||||
@ -1432,6 +1432,8 @@ private final class AmountFieldComponent: Component {
|
||||
private weak var state: EmptyComponentState?
|
||||
private var isUpdating: Bool = false
|
||||
|
||||
private var didSetValueOnce = false
|
||||
|
||||
override init(frame: CGRect) {
|
||||
self.placeholderView = ComponentView<Empty>()
|
||||
self.textField = TextFieldNodeView(frame: .zero)
|
||||
@ -1470,7 +1472,7 @@ private final class AmountFieldComponent: Component {
|
||||
}
|
||||
|
||||
self.textField.textColor = component.textColor
|
||||
if self.component?.currency != component.currency {
|
||||
if self.component?.currency != component.currency || ((self.textField.text ?? "").isEmpty && !self.didSetValueOnce) {
|
||||
if let value = component.value, value != .zero {
|
||||
var text = ""
|
||||
switch component.currency {
|
||||
@ -1480,6 +1482,7 @@ private final class AmountFieldComponent: Component {
|
||||
text = "\(formatTonAmountText(value, dateTimeFormat: PresentationDateTimeFormat(timeFormat: component.dateTimeFormat.timeFormat, dateFormat: component.dateTimeFormat.dateFormat, dateSeparator: "", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: "")))"
|
||||
}
|
||||
self.textField.text = text
|
||||
self.didSetValueOnce = true
|
||||
} else {
|
||||
self.textField.text = ""
|
||||
}
|
||||
|
||||
@ -2271,7 +2271,7 @@ final class StoryItemSetContainerSendMessage {
|
||||
}
|
||||
|
||||
let file = TelegramMediaFile(fileId: EngineMedia.Id(namespace: Namespaces.Media.LocalFile, id: fileId), partialReference: nil, resource: ICloudFileResource(urlData: item.urlData, thumbnail: false), previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: mimeType, size: Int64(item.fileSize), attributes: attributes, alternativeRepresentations: [])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), threadId: nil, replyToMessageId: replyMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: replyToStoryId, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
|
||||
let message: EnqueueMessage = .message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: file), threadId: nil, replyToMessageId: replyMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: replyToStoryId, localGroupingKey: groupingKey, correlationId: nil, bubbleUpEmojiOrStickersets: [])
|
||||
messages.append(message)
|
||||
}
|
||||
if let _ = groupingKey, messages.count % 10 == 0 {
|
||||
@ -2376,7 +2376,7 @@ final class StoryItemSetContainerSendMessage {
|
||||
threadId: nil,
|
||||
botId: results.botId,
|
||||
result: result,
|
||||
replyToMessageId: replyMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) },
|
||||
replyToMessageId: replyMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) },
|
||||
replyToStoryId: storyId,
|
||||
hideVia: hideVia,
|
||||
silentPosting: silentPosting,
|
||||
@ -2764,7 +2764,7 @@ final class StoryItemSetContainerSendMessage {
|
||||
mappedMessages.append(message)
|
||||
}
|
||||
|
||||
strongSelf.sendMessages(view: view, peer: peer, messages: mappedMessages.map { $0.withUpdatedReplyToMessageId(replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }).withUpdatedReplyToStoryId(replyToStoryId) }, silentPosting: silentPosting, scheduleTime: scheduleTime)
|
||||
strongSelf.sendMessages(view: view, peer: peer, messages: mappedMessages.map { $0.withUpdatedReplyToMessageId(replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }).withUpdatedReplyToStoryId(replyToStoryId) }, silentPosting: silentPosting, scheduleTime: scheduleTime)
|
||||
|
||||
completion()
|
||||
}
|
||||
|
||||
@ -2775,7 +2775,7 @@ private func extractAccountManagerState(records: AccountRecordsView<TelegramAcco
|
||||
if let threadId {
|
||||
replyToMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))
|
||||
}
|
||||
return enqueueMessages(account: account, peerId: peerId, messages: [EnqueueMessage.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: nil, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
|
||||
return enqueueMessages(account: account, peerId: peerId, messages: [EnqueueMessage.message(text: text, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: nil, replyToMessageId: replyToMessageId.flatMap { EngineMessageReplySubject(messageId: $0, quote: nil, todoItemId: nil) }, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
|
||||
|> map { messageIds -> MessageId? in
|
||||
if messageIds.isEmpty {
|
||||
return nil
|
||||
|
||||
@ -1539,7 +1539,7 @@ extension ChatControllerImpl {
|
||||
strongSelf.window?.presentInGlobalOverlay(controller)
|
||||
}
|
||||
|
||||
let interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { [weak self] messageId, completion in
|
||||
let interfaceInteraction = ChatPanelInterfaceInteraction(setupReplyMessage: { [weak self] messageId, todoItemId, completion in
|
||||
guard let strongSelf = self, strongSelf.isNodeLoaded else {
|
||||
return
|
||||
}
|
||||
@ -1565,7 +1565,8 @@ extension ChatControllerImpl {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({
|
||||
$0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(
|
||||
messageId: message.id,
|
||||
quote: nil
|
||||
quote: nil,
|
||||
todoItemId: todoItemId
|
||||
))
|
||||
}).updatedReplyMessage(message).updatedSearch(nil).updatedShowCommands(false) }, completion: { t in
|
||||
completion(t, {})
|
||||
@ -1588,7 +1589,8 @@ extension ChatControllerImpl {
|
||||
} else {
|
||||
let replySubject = ChatInterfaceState.ReplyMessageSubject(
|
||||
messageId: messageId,
|
||||
quote: nil
|
||||
quote: nil,
|
||||
todoItemId: todoItemId
|
||||
)
|
||||
|
||||
completion(.immediate, {
|
||||
@ -4885,7 +4887,7 @@ extension ChatControllerImpl {
|
||||
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(mappedId) {
|
||||
if toSubject.setupReply {
|
||||
Queue.mainQueue().after(0.1) {
|
||||
strongSelf.interfaceInteraction?.setupReplyMessage(mappedId, { _, f in f() })
|
||||
strongSelf.interfaceInteraction?.setupReplyMessage(mappedId, nil, { _, f in f() })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ extension ChatControllerImpl {
|
||||
break
|
||||
}
|
||||
}
|
||||
let controller = factCheckAlertController(context: self.context, updatedPresentationData: self.updatedPresentationData, value: currentText, entities: currentEntities, characterLimit: 4096, apply: { [weak self] text, entities in
|
||||
let controller = factCheckAlertController(context: self.context, updatedPresentationData: self.updatedPresentationData, value: currentText, entities: currentEntities, apply: { [weak self] text, entities in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -128,6 +128,22 @@ extension ChatControllerImpl {
|
||||
}
|
||||
}
|
||||
|
||||
if "".isEmpty {
|
||||
//TODO:localize
|
||||
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Todo_ReplyToItem, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { [weak self] c, _ in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.interfaceInteraction?.setupReplyMessage(message.id, todoItem.id, { transition, completed in
|
||||
c?.dismiss(result: .custom(transition), completion: {
|
||||
completed()
|
||||
})
|
||||
})
|
||||
})))
|
||||
}
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: self.presentationData.strings.Conversation_ContextMenuCopy, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
|
||||
f(.default)
|
||||
|
||||
|
||||
@ -316,7 +316,7 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
||||
quote = EngineMessageReplyQuote(text: trimmedText.string, offset: textSelection.offset, entities: trimmedText.entities, media: nil)
|
||||
}
|
||||
|
||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(messageId: replySubject.messageId, quote: quote)).withoutSelectionState() }) })
|
||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(messageId: replySubject.messageId, quote: quote, todoItemId: nil)).withoutSelectionState() }) })
|
||||
}
|
||||
|
||||
let items = combineLatest(queue: .mainQueue(),
|
||||
@ -381,7 +381,7 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
||||
quote = EngineMessageReplyQuote(text: trimmedText.string, offset: textSelection.offset, entities: trimmedText.entities, media: nil)
|
||||
}
|
||||
|
||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(messageId: replySubject.messageId, quote: quote)).withoutSelectionState() }) })
|
||||
selfController.updateChatPresentationInterfaceState(animated: false, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(messageId: replySubject.messageId, quote: quote, todoItemId: nil)).withoutSelectionState() }) })
|
||||
|
||||
f(.default)
|
||||
})))
|
||||
|
||||
@ -44,7 +44,8 @@ func updateChatPresentationInterfaceStateImpl(
|
||||
temporaryChatPresentationInterfaceState = temporaryChatPresentationInterfaceState.updatedInterfaceState({
|
||||
$0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(
|
||||
messageId: keyboardButtonsMessage.id,
|
||||
quote: nil
|
||||
quote: nil,
|
||||
todoItemId: nil
|
||||
)).withUpdatedMessageActionsState({ value in
|
||||
var value = value
|
||||
value.processedSetupReplyMessageId = keyboardButtonsMessage.id
|
||||
@ -67,7 +68,8 @@ func updateChatPresentationInterfaceStateImpl(
|
||||
if temporaryChatPresentationInterfaceState.interfaceState.replyMessageSubject == nil && temporaryChatPresentationInterfaceState.interfaceState.messageActionsState.processedSetupReplyMessageId != keyboardButtonsMessage.id {
|
||||
temporaryChatPresentationInterfaceState = temporaryChatPresentationInterfaceState.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(
|
||||
messageId: keyboardButtonsMessage.id,
|
||||
quote: nil
|
||||
quote: nil,
|
||||
todoItemId: nil
|
||||
)).withUpdatedMessageActionsState({ value in
|
||||
var value = value
|
||||
value.processedSetupReplyMessageId = keyboardButtonsMessage.id
|
||||
|
||||
@ -2915,7 +2915,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
var replyToMessageId: EngineMessageReplySubject?
|
||||
if postAsReply, let messageId {
|
||||
replyToMessageId = EngineMessageReplySubject(messageId: messageId, quote: nil)
|
||||
replyToMessageId = EngineMessageReplySubject(messageId: messageId, quote: nil, todoItemId: nil)
|
||||
}
|
||||
strongSelf.sendMessages([.message(text: command, attributes: attributes, inlineStickers: [:], mediaReference: nil, threadId: strongSelf.chatLocation.threadId, replyToMessageId: replyToMessageId, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])])
|
||||
}
|
||||
@ -3167,7 +3167,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
})
|
||||
}, openSearch: {
|
||||
}, setupReply: { [weak self] messageId in
|
||||
self?.interfaceInteraction?.setupReplyMessage(messageId, { _, f in f() })
|
||||
self?.interfaceInteraction?.setupReplyMessage(messageId, nil, { _, f in f() })
|
||||
}, canSetupReply: { [weak self] message in
|
||||
if message.adAttribute != nil {
|
||||
return .none
|
||||
@ -3766,9 +3766,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
let replySubject = ChatInterfaceState.ReplyMessageSubject(
|
||||
messageId: message.id,
|
||||
quote: quoteData
|
||||
quote: quoteData,
|
||||
todoItemId: nil
|
||||
)
|
||||
|
||||
if canSendMessagesToChat(strongSelf.presentationInterfaceState) {
|
||||
let _ = strongSelf.presentVoiceMessageDiscardAlert(action: {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { $0.updatedInterfaceState({ $0.withUpdatedReplyMessageSubject(replySubject) }).updatedSearch(nil).updatedShowCommands(false) }, completion: completion)
|
||||
@ -8085,13 +8085,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
break
|
||||
case let .replyThread(replyThreadMessage):
|
||||
if let effectiveMessageId = replyThreadMessage.effectiveMessageId {
|
||||
defaultReplyMessageSubject = EngineMessageReplySubject(messageId: effectiveMessageId, quote: nil)
|
||||
defaultReplyMessageSubject = EngineMessageReplySubject(messageId: effectiveMessageId, quote: nil, todoItemId: nil)
|
||||
}
|
||||
case .customChatContents:
|
||||
break
|
||||
}
|
||||
if let postSuggestionState = self.presentationInterfaceState.interfaceState.postSuggestionState, let editingOriginalMessageId = postSuggestionState.editingOriginalMessageId {
|
||||
defaultReplyMessageSubject = EngineMessageReplySubject(messageId: editingOriginalMessageId, quote: nil)
|
||||
defaultReplyMessageSubject = EngineMessageReplySubject(messageId: editingOriginalMessageId, quote: nil, todoItemId: nil)
|
||||
}
|
||||
|
||||
return messages.map { message in
|
||||
|
||||
@ -164,7 +164,8 @@ extension ChatControllerImpl {
|
||||
var updatedState = state.updatedInterfaceState({ state in
|
||||
return state.withUpdatedReplyMessageSubject(ChatInterfaceState.ReplyMessageSubject(
|
||||
messageId: message.id,
|
||||
quote: nil
|
||||
quote: nil,
|
||||
todoItemId: nil
|
||||
))
|
||||
})
|
||||
if updatedState.inputMode == .none {
|
||||
@ -184,7 +185,8 @@ extension ChatControllerImpl {
|
||||
return state.withUpdatedReplyMessageSubject((lastMessage?.id).flatMap { id in
|
||||
return ChatInterfaceState.ReplyMessageSubject(
|
||||
messageId: id,
|
||||
quote: nil
|
||||
quote: nil,
|
||||
todoItemId: nil
|
||||
)
|
||||
})
|
||||
})
|
||||
@ -218,7 +220,7 @@ extension ChatControllerImpl {
|
||||
if replyMessageSubject.messageId == lastMessage?.id {
|
||||
updatedReplyMessageSubject = nil
|
||||
} else if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(after: replyMessageSubject.messageId) {
|
||||
updatedReplyMessageSubject = ChatInterfaceState.ReplyMessageSubject(messageId: message.id, quote: nil)
|
||||
updatedReplyMessageSubject = ChatInterfaceState.ReplyMessageSubject(messageId: message.id, quote: nil, todoItemId: nil)
|
||||
}
|
||||
|
||||
strongSelf.updateChatPresentationInterfaceState(interactive: true, { state in
|
||||
|
||||
@ -636,7 +636,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
|
||||
mappedQuote = EngineMessageReplyQuote(text: quote, offset: nil, entities: [], media: nil)
|
||||
}
|
||||
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessage.id, threadMessageId: nil, quote: mappedQuote, isQuote: mappedQuote != nil))
|
||||
attributes.append(ReplyMessageAttribute(messageId: replyMessage.id, threadMessageId: nil, quote: mappedQuote, isQuote: mappedQuote != nil, todoItemId: nil))
|
||||
}
|
||||
|
||||
let message = Message(
|
||||
|
||||
@ -86,7 +86,7 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS
|
||||
}
|
||||
|
||||
if let chatPeerId {
|
||||
let panelNode = ReplyAccessoryPanelNode(context: context, chatPeerId: chatPeerId, messageId: replyMessageSubject.messageId, quote: replyMessageSubject.quote, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat, animationCache: chatControllerInteraction?.presentationContext.animationCache, animationRenderer: chatControllerInteraction?.presentationContext.animationRenderer)
|
||||
let panelNode = ReplyAccessoryPanelNode(context: context, chatPeerId: chatPeerId, messageId: replyMessageSubject.messageId, quote: replyMessageSubject.quote, todoItemId: replyMessageSubject.todoItemId, theme: chatPresentationInterfaceState.theme, strings: chatPresentationInterfaceState.strings, nameDisplayOrder: chatPresentationInterfaceState.nameDisplayOrder, dateTimeFormat: chatPresentationInterfaceState.dateTimeFormat, animationCache: chatControllerInteraction?.presentationContext.animationCache, animationRenderer: chatControllerInteraction?.presentationContext.animationRenderer)
|
||||
panelNode.interfaceInteraction = interfaceInteraction
|
||||
return panelNode
|
||||
} else {
|
||||
|
||||
@ -1162,7 +1162,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
||||
actions.append(.action(ContextMenuActionItem(text: chatPresentationInterfaceState.strings.Conversation_ContextMenuReply, icon: { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Reply"), color: theme.actionSheet.primaryTextColor)
|
||||
}, action: { c, _ in
|
||||
interfaceInteraction.setupReplyMessage(messages[0].id, { transition, completed in
|
||||
interfaceInteraction.setupReplyMessage(messages[0].id, nil, { transition, completed in
|
||||
c?.dismiss(result: .custom(transition), completion: {
|
||||
completed()
|
||||
})
|
||||
|
||||
@ -2732,6 +2732,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
mappedSource = .todo
|
||||
case let .auth(price):
|
||||
mappedSource = .auth(price)
|
||||
case let .premiumGift(file):
|
||||
mappedSource = .premiumGift(file)
|
||||
}
|
||||
return mappedSource
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user