mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Update API [skip ci]
This commit is contained in:
parent
d64208df43
commit
e3ee1dde7e
@ -13469,15 +13469,21 @@ Sorry for the inconvenience.";
|
|||||||
"Gift.View.Status.NonUnique" = "Non-Unique";
|
"Gift.View.Status.NonUnique" = "Non-Unique";
|
||||||
"Gift.View.Status.Upgrade" = "upgrade";
|
"Gift.View.Status.Upgrade" = "upgrade";
|
||||||
"Gift.View.DisplayedInfoHide" = "The gift is visible on your Page. [Hide >]()";
|
"Gift.View.DisplayedInfoHide" = "The gift is visible on your Page. [Hide >]()";
|
||||||
|
"Gift.View.HiddenInfoShow" = "This gift is hidden. Only you can see it. [Show >]()";
|
||||||
|
|
||||||
"Gift.Upgrade.Title" = "Upgrade Gift";
|
"Gift.Upgrade.Title" = "Upgrade Gift";
|
||||||
|
"Gift.Upgrade.IncludeTitle" = "Make Unique";
|
||||||
"Gift.Upgrade.Description" = "Turn your gift into a unique collectible that you can transfer or auction.";
|
"Gift.Upgrade.Description" = "Turn your gift into a unique collectible that you can transfer or auction.";
|
||||||
|
"Gift.Upgrade.IncludeDescription" = "Let %@ turn your gift into a unique collectible.";
|
||||||
"Gift.Upgrade.Unique.Title" = "Unique";
|
"Gift.Upgrade.Unique.Title" = "Unique";
|
||||||
"Gift.Upgrade.Unique.Description" = "Get a unique number, model backdrop and and symbol for your gift.";
|
"Gift.Upgrade.Unique.Description" = "Get a unique number, model, backdrop, and symbol for your gift.";
|
||||||
|
"Gift.Upgrade.Unique.IncludeDescription" = "The recipient will get a unique number, model, backdrop, and symbol for the gift.";
|
||||||
"Gift.Upgrade.Transferable.Title" = "Transferable";
|
"Gift.Upgrade.Transferable.Title" = "Transferable";
|
||||||
"Gift.Upgrade.Transferable.Description" = "Send your upgraded gift to any of your friends on Telegram.";
|
"Gift.Upgrade.Transferable.Description" = "Send your upgraded gift to any of your friends on Telegram.";
|
||||||
|
"Gift.Upgrade.Transferable.IncludeDescription" = "The recipient will be able to send the gift to anyone Telegram.";
|
||||||
"Gift.Upgrade.Tradable.Title" = "Tradable";
|
"Gift.Upgrade.Tradable.Title" = "Tradable";
|
||||||
"Gift.Upgrade.Tradable.Description" = "Sell or auction your gift on third-party NFT marketplaces.";
|
"Gift.Upgrade.Tradable.Description" = "Sell or auction your gift on third-party NFT marketplaces.";
|
||||||
|
"Gift.Upgrade.Tradable.IncludeDescription" = "The recipient will be able to auction the gift on third-party NFT marketplaces.";
|
||||||
"Gift.Upgrade.Soon" = "SOON";
|
"Gift.Upgrade.Soon" = "SOON";
|
||||||
"Gift.Upgrade.AddName" = "Add sender's name";
|
"Gift.Upgrade.AddName" = "Add sender's name";
|
||||||
"Gift.Upgrade.AddNameAndComment" = "Add sender's name and comment";
|
"Gift.Upgrade.AddNameAndComment" = "Add sender's name and comment";
|
||||||
@ -13525,6 +13531,7 @@ Sorry for the inconvenience.";
|
|||||||
"Gift.Transfer.Confirmation.Transfer" = "Transfer for";
|
"Gift.Transfer.Confirmation.Transfer" = "Transfer for";
|
||||||
"Gift.Transfer.Confirmation.TransferFree" = "Transfer";
|
"Gift.Transfer.Confirmation.TransferFree" = "Transfer";
|
||||||
|
|
||||||
|
"Gift.View.UpgradeForFree" = "Upgrade for Free";
|
||||||
"Gift.View.KeepUpgradeOrConvertDescription" = "You can keep this gift, upgrade it, or sell it for %@. [More About Stars >]()";
|
"Gift.View.KeepUpgradeOrConvertDescription" = "You can keep this gift, upgrade it, or sell it for %@. [More About Stars >]()";
|
||||||
|
|
||||||
"PeerInfo.VerificationInfo.Bot" = "This bot is verified as official by the representatives of Telegram.";
|
"PeerInfo.VerificationInfo.Bot" = "This bot is verified as official by the representatives of Telegram.";
|
||||||
@ -13537,8 +13544,21 @@ Sorry for the inconvenience.";
|
|||||||
"Gift.Send.Upgrade" = "Make Unique for %@";
|
"Gift.Send.Upgrade" = "Make Unique for %@";
|
||||||
"Gift.Send.Upgrade.Info" = "Enable this to let %1$@ turn your gift into a unique collectible. [Learn More >]()";
|
"Gift.Send.Upgrade.Info" = "Enable this to let %1$@ turn your gift into a unique collectible. [Learn More >]()";
|
||||||
|
|
||||||
|
"Notification.StarGift.Unpack" = "Unpack";
|
||||||
|
|
||||||
|
"Notification.StarGift.Model" = "Model";
|
||||||
|
"Notification.StarGift.Backdrop" = "Backdrop";
|
||||||
|
"Notification.StarGift.Symbol" = "Symbol";
|
||||||
|
|
||||||
|
"Notification.StarGift.Gift" = "gift";
|
||||||
|
|
||||||
"Notification.StarsGift.Upgrade" = "%@ turned the gift from you to a unique collectible";
|
"Notification.StarsGift.Upgrade" = "%@ turned the gift from you to a unique collectible";
|
||||||
"Notification.StarsGift.UpgradeYou" = "You turned the gift from %@ to a unique collectible";
|
"Notification.StarsGift.UpgradeYou" = "You turned the gift from %@ to a unique collectible";
|
||||||
|
|
||||||
"Notification.StarsGift.Transfer" = "%@ transferred you a unique collectible";
|
"Notification.StarsGift.Transfer" = "%@ transferred you a unique collectible";
|
||||||
"Notification.StarsGift.TransferYou" = "You transferred a unique collectible";
|
"Notification.StarsGift.TransferYou" = "You transferred a unique collectible";
|
||||||
|
|
||||||
|
"Notification.StarGift.Subtitle.Refunded" = "This gift cannot be converted to Stars because the payment related to it was refunded.";
|
||||||
|
"Notification.StarGift.Subtitle.Downgraded" = "This gift was downgraded because a request to refund the payment related to this gift was made, and the money was returned.";
|
||||||
|
|
||||||
|
"Gift.View.KeepOrUpgradeDescription" = "You can keep this gift or upgrade it.";
|
||||||
|
@ -3107,7 +3107,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
var titleLeftOffset: CGFloat = 0.0
|
var titleLeftOffset: CGFloat = 0.0
|
||||||
if let currentVerifiedIconContent {
|
if let currentVerifiedIconContent {
|
||||||
if titleLeftOffset.isZero, currentVerifiedIconContent != .none {
|
if titleLeftOffset.isZero, case .animation = currentVerifiedIconContent {
|
||||||
titleLeftOffset += 20.0
|
titleLeftOffset += 20.0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3127,10 +3127,6 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let currentCredibilityIconContent {
|
if let currentCredibilityIconContent {
|
||||||
if titleLeftOffset.isZero, case .verified = currentCredibilityIconContent {
|
|
||||||
titleLeftOffset += 20.0
|
|
||||||
}
|
|
||||||
|
|
||||||
if titleIconsWidth.isZero {
|
if titleIconsWidth.isZero {
|
||||||
titleIconsWidth += 4.0
|
titleIconsWidth += 4.0
|
||||||
} else {
|
} else {
|
||||||
@ -4500,11 +4496,8 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
)
|
)
|
||||||
strongSelf.credibilityIconComponent = credibilityIconComponent
|
strongSelf.credibilityIconComponent = credibilityIconComponent
|
||||||
|
|
||||||
var iconOrigin: CGFloat = nextTitleIconOrigin
|
let iconOrigin: CGFloat = nextTitleIconOrigin
|
||||||
let containerSize = CGSize(width: 20.0, height: 20.0)
|
let containerSize = CGSize(width: 20.0, height: 20.0)
|
||||||
if case .verified = currentCredibilityIconContent {
|
|
||||||
iconOrigin = contentRect.origin.x
|
|
||||||
}
|
|
||||||
let iconSize = credibilityIconView.update(
|
let iconSize = credibilityIconView.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(credibilityIconComponent),
|
component: AnyComponent(credibilityIconComponent),
|
||||||
@ -4512,10 +4505,7 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
containerSize: containerSize
|
containerSize: containerSize
|
||||||
)
|
)
|
||||||
transition.updateFrame(view: credibilityIconView, frame: CGRect(origin: CGPoint(x: iconOrigin, y: floorToScreenPixels(titleFrame.maxY - lastLineRect.height * 0.5 - iconSize.height / 2.0) - UIScreenPixel), size: iconSize))
|
transition.updateFrame(view: credibilityIconView, frame: CGRect(origin: CGPoint(x: iconOrigin, y: floorToScreenPixels(titleFrame.maxY - lastLineRect.height * 0.5 - iconSize.height / 2.0) - UIScreenPixel), size: iconSize))
|
||||||
if case .verified = currentCredibilityIconContent {
|
nextTitleIconOrigin += credibilityIconView.bounds.width + 4.0
|
||||||
} else {
|
|
||||||
nextTitleIconOrigin += credibilityIconView.bounds.width + 4.0
|
|
||||||
}
|
|
||||||
} else if let credibilityIconView = strongSelf.credibilityIconView {
|
} else if let credibilityIconView = strongSelf.credibilityIconView {
|
||||||
strongSelf.credibilityIconView = nil
|
strongSelf.credibilityIconView = nil
|
||||||
credibilityIconView.removeFromSuperview()
|
credibilityIconView.removeFromSuperview()
|
||||||
@ -4541,7 +4531,12 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
)
|
)
|
||||||
strongSelf.verifiedIconComponent = verifiedIconComponent
|
strongSelf.verifiedIconComponent = verifiedIconComponent
|
||||||
|
|
||||||
let iconOrigin = contentRect.origin.x
|
let iconOrigin: CGFloat
|
||||||
|
if case .animation = currentVerifiedIconContent {
|
||||||
|
iconOrigin = contentRect.origin.x
|
||||||
|
} else {
|
||||||
|
iconOrigin = nextTitleIconOrigin
|
||||||
|
}
|
||||||
let containerSize = CGSize(width: 16.0, height: 16.0)
|
let containerSize = CGSize(width: 16.0, height: 16.0)
|
||||||
|
|
||||||
let iconSize = verifiedIconView.update(
|
let iconSize = verifiedIconView.update(
|
||||||
|
@ -582,77 +582,6 @@ private func makeLayerSubtreeSnapshot(layer: CALayer) -> CALayer? {
|
|||||||
view.cornerRadius = layer.cornerRadius
|
view.cornerRadius = layer.cornerRadius
|
||||||
view.backgroundColor = layer.backgroundColor
|
view.backgroundColor = layer.backgroundColor
|
||||||
view.layerTintColor = layer.layerTintColor
|
view.layerTintColor = layer.layerTintColor
|
||||||
|
|
||||||
/*
|
|
||||||
open var path: CGPath?
|
|
||||||
|
|
||||||
|
|
||||||
/* The color to fill the path, or nil for no fill. Defaults to opaque
|
|
||||||
* black. Animatable. */
|
|
||||||
|
|
||||||
open var fillColor: CGColor?
|
|
||||||
|
|
||||||
|
|
||||||
/* The fill rule used when filling the path. Options are `non-zero' and
|
|
||||||
* `even-odd'. Defaults to `non-zero'. */
|
|
||||||
|
|
||||||
open var fillRule: CAShapeLayerFillRule
|
|
||||||
|
|
||||||
|
|
||||||
/* The color to fill the path's stroked outline, or nil for no stroking.
|
|
||||||
* Defaults to nil. Animatable. */
|
|
||||||
|
|
||||||
open var strokeColor: CGColor?
|
|
||||||
|
|
||||||
|
|
||||||
/* These values define the subregion of the path used to draw the
|
|
||||||
* stroked outline. The values must be in the range [0,1] with zero
|
|
||||||
* representing the start of the path and one the end. Values in
|
|
||||||
* between zero and one are interpolated linearly along the path
|
|
||||||
* length. strokeStart defaults to zero and strokeEnd to one. Both are
|
|
||||||
* animatable. */
|
|
||||||
|
|
||||||
open var strokeStart: CGFloat
|
|
||||||
|
|
||||||
open var strokeEnd: CGFloat
|
|
||||||
|
|
||||||
|
|
||||||
/* The line width used when stroking the path. Defaults to one.
|
|
||||||
* Animatable. */
|
|
||||||
|
|
||||||
open var lineWidth: CGFloat
|
|
||||||
|
|
||||||
|
|
||||||
/* The miter limit used when stroking the path. Defaults to ten.
|
|
||||||
* Animatable. */
|
|
||||||
|
|
||||||
open var miterLimit: CGFloat
|
|
||||||
|
|
||||||
|
|
||||||
/* The cap style used when stroking the path. Options are `butt', `round'
|
|
||||||
* and `square'. Defaults to `butt'. */
|
|
||||||
|
|
||||||
open var lineCap: CAShapeLayerLineCap
|
|
||||||
|
|
||||||
|
|
||||||
/* The join style used when stroking the path. Options are `miter', `round'
|
|
||||||
* and `bevel'. Defaults to `miter'. */
|
|
||||||
|
|
||||||
open var lineJoin: CAShapeLayerLineJoin
|
|
||||||
|
|
||||||
|
|
||||||
/* The phase of the dashing pattern applied when creating the stroke.
|
|
||||||
* Defaults to zero. Animatable. */
|
|
||||||
|
|
||||||
open var lineDashPhase: CGFloat
|
|
||||||
|
|
||||||
|
|
||||||
/* The dash pattern (an array of NSNumbers) applied when creating the
|
|
||||||
* stroked version of the path. Defaults to nil. */
|
|
||||||
|
|
||||||
open var lineDashPattern: [NSNumber]?
|
|
||||||
*/
|
|
||||||
|
|
||||||
view.path = layer.path
|
view.path = layer.path
|
||||||
view.fillColor = layer.fillColor
|
view.fillColor = layer.fillColor
|
||||||
view.fillRule = layer.fillRule
|
view.fillRule = layer.fillRule
|
||||||
@ -666,6 +595,40 @@ private func makeLayerSubtreeSnapshot(layer: CALayer) -> CALayer? {
|
|||||||
view.lineDashPhase = layer.lineDashPhase
|
view.lineDashPhase = layer.lineDashPhase
|
||||||
view.lineDashPattern = layer.lineDashPattern
|
view.lineDashPattern = layer.lineDashPattern
|
||||||
|
|
||||||
|
if let sublayers = layer.sublayers {
|
||||||
|
for sublayer in sublayers {
|
||||||
|
let subtree = makeLayerSubtreeSnapshot(layer: sublayer)
|
||||||
|
if let subtree = subtree {
|
||||||
|
subtree.transform = sublayer.transform
|
||||||
|
subtree.position = sublayer.position
|
||||||
|
subtree.bounds = sublayer.bounds
|
||||||
|
subtree.anchorPoint = sublayer.anchorPoint
|
||||||
|
view.addSublayer(subtree)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return view
|
||||||
|
} else if let layer = layer as? CAGradientLayer {
|
||||||
|
let view = CAGradientLayer()
|
||||||
|
view.isHidden = layer.isHidden
|
||||||
|
view.opacity = layer.opacity
|
||||||
|
view.contents = layer.contents
|
||||||
|
view.contentsRect = layer.contentsRect
|
||||||
|
view.contentsScale = layer.contentsScale
|
||||||
|
view.contentsCenter = layer.contentsCenter
|
||||||
|
view.contentsGravity = layer.contentsGravity
|
||||||
|
view.masksToBounds = layer.masksToBounds
|
||||||
|
view.cornerRadius = layer.cornerRadius
|
||||||
|
view.backgroundColor = layer.backgroundColor
|
||||||
|
view.layerTintColor = layer.layerTintColor
|
||||||
|
view.colors = layer.colors
|
||||||
|
view.locations = layer.locations
|
||||||
|
view.startPoint = layer.startPoint
|
||||||
|
view.endPoint = layer.endPoint
|
||||||
|
view.type = layer.type
|
||||||
|
|
||||||
if let sublayers = layer.sublayers {
|
if let sublayers = layer.sublayers {
|
||||||
for sublayer in sublayers {
|
for sublayer in sublayers {
|
||||||
let subtree = makeLayerSubtreeSnapshot(layer: sublayer)
|
let subtree = makeLayerSubtreeSnapshot(layer: sublayer)
|
||||||
|
@ -47,6 +47,7 @@ final class DrawingMetalView: MTKView {
|
|||||||
super.init(frame: CGRect(origin: .zero, size: size), device: device)
|
super.init(frame: CGRect(origin: .zero, size: size), device: device)
|
||||||
|
|
||||||
self.drawableSize = self.size
|
self.drawableSize = self.size
|
||||||
|
self.colorPixelFormat = .bgra8Unorm
|
||||||
self.autoResizeDrawable = false
|
self.autoResizeDrawable = false
|
||||||
self.isOpaque = false
|
self.isOpaque = false
|
||||||
self.contentScaleFactor = 1.0
|
self.contentScaleFactor = 1.0
|
||||||
@ -123,7 +124,7 @@ final class DrawingMetalView: MTKView {
|
|||||||
let pipelineDescription = MTLRenderPipelineDescriptor()
|
let pipelineDescription = MTLRenderPipelineDescriptor()
|
||||||
pipelineDescription.vertexFunction = vertexFunction
|
pipelineDescription.vertexFunction = vertexFunction
|
||||||
pipelineDescription.fragmentFunction = fragmentFunction
|
pipelineDescription.fragmentFunction = fragmentFunction
|
||||||
pipelineDescription.colorAttachments[0].pixelFormat = colorPixelFormat
|
pipelineDescription.colorAttachments[0].pixelFormat = self.colorPixelFormat
|
||||||
|
|
||||||
do {
|
do {
|
||||||
self.pipelineState = try self.device?.makeRenderPipelineState(descriptor: pipelineDescription)
|
self.pipelineState = try self.device?.makeRenderPipelineState(descriptor: pipelineDescription)
|
||||||
@ -250,6 +251,7 @@ private class Drawable {
|
|||||||
attachment?.texture = self.texture?.texture
|
attachment?.texture = self.texture?.texture
|
||||||
attachment?.loadAction = .load
|
attachment?.loadAction = .load
|
||||||
attachment?.storeAction = .store
|
attachment?.storeAction = .store
|
||||||
|
attachment?.clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0)
|
||||||
|
|
||||||
self.updateBuffer(with: size)
|
self.updateBuffer(with: size)
|
||||||
}
|
}
|
||||||
@ -288,7 +290,6 @@ private class Drawable {
|
|||||||
return commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)
|
return commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal func commit(wait: Bool = false) {
|
internal func commit(wait: Bool = false) {
|
||||||
self.commandBuffer?.commit()
|
self.commandBuffer?.commit()
|
||||||
if wait {
|
if wait {
|
||||||
@ -673,9 +674,9 @@ final class Texture {
|
|||||||
origin: MTLOrigin(x: 0, y: 0, z: 0),
|
origin: MTLOrigin(x: 0, y: 0, z: 0),
|
||||||
size: MTLSize(width: self.width, height: self.height, depth: 1)
|
size: MTLSize(width: self.width, height: self.height, depth: 1)
|
||||||
)
|
)
|
||||||
let data = Data(capacity: Int(self.bytesPerRow * self.height))
|
let zeroData = [UInt8](repeating: 0, count: self.bytesPerRow * self.height)
|
||||||
if let bytes = data.withUnsafeBytes({ $0.baseAddress }) {
|
zeroData.withUnsafeBytes { bytes in
|
||||||
self.texture.replace(region: region, mipmapLevel: 0, withBytes: bytes, bytesPerRow: self.bytesPerRow)
|
self.texture.replace(region: region, mipmapLevel: 0, withBytes: bytes.baseAddress!, bytesPerRow: self.bytesPerRow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,7 +583,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||||||
dict[-1434950843] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) }
|
dict[-1434950843] = { return Api.MessageAction.parse_messageActionSetChatTheme($0) }
|
||||||
dict[1348510708] = { return Api.MessageAction.parse_messageActionSetChatWallPaper($0) }
|
dict[1348510708] = { return Api.MessageAction.parse_messageActionSetChatWallPaper($0) }
|
||||||
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
|
dict[1007897979] = { return Api.MessageAction.parse_messageActionSetMessagesTTL($0) }
|
||||||
dict[1785072017] = { return Api.MessageAction.parse_messageActionStarGift($0) }
|
dict[-655036249] = { return Api.MessageAction.parse_messageActionStarGift($0) }
|
||||||
dict[638024601] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
|
dict[638024601] = { return Api.MessageAction.parse_messageActionStarGiftUnique($0) }
|
||||||
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
|
dict[1474192222] = { return Api.MessageAction.parse_messageActionSuggestProfilePhoto($0) }
|
||||||
dict[228168278] = { return Api.MessageAction.parse_messageActionTopicCreate($0) }
|
dict[228168278] = { return Api.MessageAction.parse_messageActionTopicCreate($0) }
|
||||||
|
@ -373,7 +373,7 @@ public extension Api {
|
|||||||
case messageActionSetChatTheme(emoticon: String)
|
case messageActionSetChatTheme(emoticon: String)
|
||||||
case messageActionSetChatWallPaper(flags: Int32, wallpaper: Api.WallPaper)
|
case messageActionSetChatWallPaper(flags: Int32, wallpaper: Api.WallPaper)
|
||||||
case messageActionSetMessagesTTL(flags: Int32, period: Int32, autoSettingFrom: Int64?)
|
case messageActionSetMessagesTTL(flags: Int32, period: Int32, autoSettingFrom: Int64?)
|
||||||
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeStars: Int64?)
|
case messageActionStarGift(flags: Int32, gift: Api.StarGift, message: Api.TextWithEntities?, convertStars: Int64?, upgradeMsgId: Int32?, upgradeStars: Int64?)
|
||||||
case messageActionStarGiftUnique(flags: Int32, gift: Api.StarGift, canExportAt: Int32?, transferStars: Int64?)
|
case messageActionStarGiftUnique(flags: Int32, gift: Api.StarGift, canExportAt: Int32?, transferStars: Int64?)
|
||||||
case messageActionSuggestProfilePhoto(photo: Api.Photo)
|
case messageActionSuggestProfilePhoto(photo: Api.Photo)
|
||||||
case messageActionTopicCreate(flags: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?)
|
case messageActionTopicCreate(flags: Int32, title: String, iconColor: Int32, iconEmojiId: Int64?)
|
||||||
@ -720,14 +720,15 @@ public extension Api {
|
|||||||
serializeInt32(period, buffer: buffer, boxed: false)
|
serializeInt32(period, buffer: buffer, boxed: false)
|
||||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(autoSettingFrom!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 0) != 0 {serializeInt64(autoSettingFrom!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeStars):
|
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars):
|
||||||
if boxed {
|
if boxed {
|
||||||
buffer.appendInt32(1785072017)
|
buffer.appendInt32(-655036249)
|
||||||
}
|
}
|
||||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||||
gift.serialize(buffer, true)
|
gift.serialize(buffer, true)
|
||||||
if Int(flags) & Int(1 << 1) != 0 {message!.serialize(buffer, true)}
|
if Int(flags) & Int(1 << 1) != 0 {message!.serialize(buffer, true)}
|
||||||
if Int(flags) & Int(1 << 4) != 0 {serializeInt64(convertStars!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 4) != 0 {serializeInt64(convertStars!, buffer: buffer, boxed: false)}
|
||||||
|
if Int(flags) & Int(1 << 5) != 0 {serializeInt32(upgradeMsgId!, buffer: buffer, boxed: false)}
|
||||||
if Int(flags) & Int(1 << 8) != 0 {serializeInt64(upgradeStars!, buffer: buffer, boxed: false)}
|
if Int(flags) & Int(1 << 8) != 0 {serializeInt64(upgradeStars!, buffer: buffer, boxed: false)}
|
||||||
break
|
break
|
||||||
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars):
|
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars):
|
||||||
@ -864,8 +865,8 @@ public extension Api {
|
|||||||
return ("messageActionSetChatWallPaper", [("flags", flags as Any), ("wallpaper", wallpaper as Any)])
|
return ("messageActionSetChatWallPaper", [("flags", flags as Any), ("wallpaper", wallpaper as Any)])
|
||||||
case .messageActionSetMessagesTTL(let flags, let period, let autoSettingFrom):
|
case .messageActionSetMessagesTTL(let flags, let period, let autoSettingFrom):
|
||||||
return ("messageActionSetMessagesTTL", [("flags", flags as Any), ("period", period as Any), ("autoSettingFrom", autoSettingFrom as Any)])
|
return ("messageActionSetMessagesTTL", [("flags", flags as Any), ("period", period as Any), ("autoSettingFrom", autoSettingFrom as Any)])
|
||||||
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeStars):
|
case .messageActionStarGift(let flags, let gift, let message, let convertStars, let upgradeMsgId, let upgradeStars):
|
||||||
return ("messageActionStarGift", [("flags", flags as Any), ("gift", gift as Any), ("message", message as Any), ("convertStars", convertStars as Any), ("upgradeStars", upgradeStars as Any)])
|
return ("messageActionStarGift", [("flags", flags as Any), ("gift", gift as Any), ("message", message as Any), ("convertStars", convertStars as Any), ("upgradeMsgId", upgradeMsgId as Any), ("upgradeStars", upgradeStars as Any)])
|
||||||
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars):
|
case .messageActionStarGiftUnique(let flags, let gift, let canExportAt, let transferStars):
|
||||||
return ("messageActionStarGiftUnique", [("flags", flags as Any), ("gift", gift as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any)])
|
return ("messageActionStarGiftUnique", [("flags", flags as Any), ("gift", gift as Any), ("canExportAt", canExportAt as Any), ("transferStars", transferStars as Any)])
|
||||||
case .messageActionSuggestProfilePhoto(let photo):
|
case .messageActionSuggestProfilePhoto(let photo):
|
||||||
@ -1528,15 +1529,18 @@ public extension Api {
|
|||||||
} }
|
} }
|
||||||
var _4: Int64?
|
var _4: Int64?
|
||||||
if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt64() }
|
if Int(_1!) & Int(1 << 4) != 0 {_4 = reader.readInt64() }
|
||||||
var _5: Int64?
|
var _5: Int32?
|
||||||
if Int(_1!) & Int(1 << 8) != 0 {_5 = reader.readInt64() }
|
if Int(_1!) & Int(1 << 5) != 0 {_5 = reader.readInt32() }
|
||||||
|
var _6: Int64?
|
||||||
|
if Int(_1!) & Int(1 << 8) != 0 {_6 = reader.readInt64() }
|
||||||
let _c1 = _1 != nil
|
let _c1 = _1 != nil
|
||||||
let _c2 = _2 != nil
|
let _c2 = _2 != nil
|
||||||
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
|
||||||
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
|
let _c4 = (Int(_1!) & Int(1 << 4) == 0) || _4 != nil
|
||||||
let _c5 = (Int(_1!) & Int(1 << 8) == 0) || _5 != nil
|
let _c5 = (Int(_1!) & Int(1 << 5) == 0) || _5 != nil
|
||||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
let _c6 = (Int(_1!) & Int(1 << 8) == 0) || _6 != nil
|
||||||
return Api.MessageAction.messageActionStarGift(flags: _1!, gift: _2!, message: _3, convertStars: _4, upgradeStars: _5)
|
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
|
||||||
|
return Api.MessageAction.messageActionStarGift(flags: _1!, gift: _2!, message: _3, convertStars: _4, upgradeMsgId: _5, upgradeStars: _6)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
|
@ -9463,6 +9463,25 @@ public extension Api.functions.payments {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public extension Api.functions.payments {
|
||||||
|
static func getUserStarGift(msgId: [Int32]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.UserStarGifts>) {
|
||||||
|
let buffer = Buffer()
|
||||||
|
buffer.appendInt32(-1258101595)
|
||||||
|
buffer.appendInt32(481674261)
|
||||||
|
buffer.appendInt32(Int32(msgId.count))
|
||||||
|
for item in msgId {
|
||||||
|
serializeInt32(item, buffer: buffer, boxed: false)
|
||||||
|
}
|
||||||
|
return (FunctionDescription(name: "payments.getUserStarGift", parameters: [("msgId", String(describing: msgId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.payments.UserStarGifts? in
|
||||||
|
let reader = BufferReader(buffer)
|
||||||
|
var result: Api.payments.UserStarGifts?
|
||||||
|
if let signature = reader.readInt32() {
|
||||||
|
result = Api.parse(reader, signature: signature) as? Api.payments.UserStarGifts
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
public extension Api.functions.payments {
|
public extension Api.functions.payments {
|
||||||
static func getUserStarGifts(userId: Api.InputUser, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.UserStarGifts>) {
|
static func getUserStarGifts(userId: Api.InputUser, offset: String, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.payments.UserStarGifts>) {
|
||||||
let buffer = Buffer()
|
let buffer = Buffer()
|
||||||
|
@ -132,7 +132,6 @@ enum AccountStateMutationOperation {
|
|||||||
case UpdateStarsBalance(peerId: PeerId, balance: Api.StarsAmount)
|
case UpdateStarsBalance(peerId: PeerId, balance: Api.StarsAmount)
|
||||||
case UpdateStarsRevenueStatus(peerId: PeerId, status: StarsRevenueStats.Balances)
|
case UpdateStarsRevenueStatus(peerId: PeerId, status: StarsRevenueStats.Balances)
|
||||||
case UpdateStarsReactionsAreAnonymousByDefault(isAnonymous: Bool)
|
case UpdateStarsReactionsAreAnonymousByDefault(isAnonymous: Bool)
|
||||||
case UpdateUpgradedStarGift(from: Api.UserStarGift, to: Api.UserStarGift)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HoleFromPreviousState {
|
struct HoleFromPreviousState {
|
||||||
@ -703,13 +702,9 @@ struct AccountMutableState {
|
|||||||
self.addOperation(.UpdateStarsReactionsAreAnonymousByDefault(isAnonymous: isAnonymous))
|
self.addOperation(.UpdateStarsReactionsAreAnonymousByDefault(isAnonymous: isAnonymous))
|
||||||
}
|
}
|
||||||
|
|
||||||
mutating func updateUpgradedStarGift(from: Api.UserStarGift, to: Api.UserStarGift) {
|
|
||||||
self.addOperation(.UpdateUpgradedStarGift(from: from, to: to))
|
|
||||||
}
|
|
||||||
|
|
||||||
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||||
switch operation {
|
switch operation {
|
||||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .UpdateWallpaper, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter, .UpdateReadThread, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateMessagesPinned, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsAreAnonymousByDefault, .UpdateUpgradedStarGift:
|
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .UpdateWallpaper, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter, .UpdateReadThread, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateMessagesPinned, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsAreAnonymousByDefault:
|
||||||
break
|
break
|
||||||
case let .AddMessages(messages, location):
|
case let .AddMessages(messages, location):
|
||||||
for message in messages {
|
for message in messages {
|
||||||
@ -856,7 +851,6 @@ struct AccountReplayedFinalState {
|
|||||||
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
|
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
|
||||||
let updatedStarsBalance: [PeerId: StarsAmount]
|
let updatedStarsBalance: [PeerId: StarsAmount]
|
||||||
let updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]
|
let updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]
|
||||||
let updatedUpgradedStarGifts:[(ProfileGiftsContext.State.StarGift, ProfileGiftsContext.State.StarGift)]
|
|
||||||
let sentScheduledMessageIds: Set<MessageId>
|
let sentScheduledMessageIds: Set<MessageId>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -888,13 +882,12 @@ struct AccountFinalStateEvents {
|
|||||||
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
|
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
|
||||||
let updatedStarsBalance: [PeerId: StarsAmount]
|
let updatedStarsBalance: [PeerId: StarsAmount]
|
||||||
let updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]
|
let updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances]
|
||||||
let updatedUpgradedStarGifts: [(ProfileGiftsContext.State.StarGift, ProfileGiftsContext.State.StarGift)]
|
|
||||||
|
|
||||||
var isEmpty: Bool {
|
var isEmpty: Bool {
|
||||||
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.sentScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.storyUpdates.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.dismissBotWebViews.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty && !self.updateConfig && !self.isPremiumUpdated && self.updatedRevenueBalances.isEmpty && self.updatedStarsBalance.isEmpty && self.updatedStarsRevenueStatus.isEmpty && self.updatedUpgradedStarGifts.isEmpty
|
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.sentScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.storyUpdates.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.dismissBotWebViews.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty && !self.updateConfig && !self.isPremiumUpdated && self.updatedRevenueBalances.isEmpty && self.updatedStarsBalance.isEmpty && self.updatedStarsRevenueStatus.isEmpty
|
||||||
}
|
}
|
||||||
|
|
||||||
init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: MessageReaction.Reaction, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], storyUpdates: [InternalStoryUpdate] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], dismissBotWebViews: [Int64] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:], updatedStarsBalance: [PeerId: StarsAmount] = [:], updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:], sentScheduledMessageIds: Set<MessageId> = Set(), updatedUpgradedStarGifts: [(ProfileGiftsContext.State.StarGift, ProfileGiftsContext.State.StarGift)] = []) {
|
init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: MessageReaction.Reaction, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], storyUpdates: [InternalStoryUpdate] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], dismissBotWebViews: [Int64] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:], updatedStarsBalance: [PeerId: StarsAmount] = [:], updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:], sentScheduledMessageIds: Set<MessageId> = Set()) {
|
||||||
self.addedIncomingMessageIds = addedIncomingMessageIds
|
self.addedIncomingMessageIds = addedIncomingMessageIds
|
||||||
self.addedReactionEvents = addedReactionEvents
|
self.addedReactionEvents = addedReactionEvents
|
||||||
self.wasScheduledMessageIds = wasScheduledMessageIds
|
self.wasScheduledMessageIds = wasScheduledMessageIds
|
||||||
@ -921,7 +914,6 @@ struct AccountFinalStateEvents {
|
|||||||
self.updatedRevenueBalances = updatedRevenueBalances
|
self.updatedRevenueBalances = updatedRevenueBalances
|
||||||
self.updatedStarsBalance = updatedStarsBalance
|
self.updatedStarsBalance = updatedStarsBalance
|
||||||
self.updatedStarsRevenueStatus = updatedStarsRevenueStatus
|
self.updatedStarsRevenueStatus = updatedStarsRevenueStatus
|
||||||
self.updatedUpgradedStarGifts = updatedUpgradedStarGifts
|
|
||||||
self.sentScheduledMessageIds = sentScheduledMessageIds
|
self.sentScheduledMessageIds = sentScheduledMessageIds
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,7 +944,6 @@ struct AccountFinalStateEvents {
|
|||||||
self.updatedRevenueBalances = state.updatedRevenueBalances
|
self.updatedRevenueBalances = state.updatedRevenueBalances
|
||||||
self.updatedStarsBalance = state.updatedStarsBalance
|
self.updatedStarsBalance = state.updatedStarsBalance
|
||||||
self.updatedStarsRevenueStatus = state.updatedStarsRevenueStatus
|
self.updatedStarsRevenueStatus = state.updatedStarsRevenueStatus
|
||||||
self.updatedUpgradedStarGifts = state.updatedUpgradedStarGifts
|
|
||||||
self.sentScheduledMessageIds = state.sentScheduledMessageIds
|
self.sentScheduledMessageIds = state.sentScheduledMessageIds
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -986,6 +977,6 @@ struct AccountFinalStateEvents {
|
|||||||
var sentScheduledMessageIds = self.sentScheduledMessageIds
|
var sentScheduledMessageIds = self.sentScheduledMessageIds
|
||||||
sentScheduledMessageIds.formUnion(other.sentScheduledMessageIds)
|
sentScheduledMessageIds.formUnion(other.sentScheduledMessageIds)
|
||||||
|
|
||||||
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, addedReactionEvents: self.addedReactionEvents + other.addedReactionEvents, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, deletedMessageIds: self.deletedMessageIds + other.deletedMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, updatedGroupCallParticipants: self.updatedGroupCallParticipants + other.updatedGroupCallParticipants, storyUpdates: self.storyUpdates + other.storyUpdates, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, dismissBotWebViews: self.dismissBotWebViews + other.dismissBotWebViews, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated, updatedIncomingThreadReadStates: self.updatedIncomingThreadReadStates.merging(other.updatedIncomingThreadReadStates, uniquingKeysWith: { lhs, _ in lhs }), updateConfig: updateConfig, isPremiumUpdated: isPremiumUpdated, updatedRevenueBalances: self.updatedRevenueBalances.merging(other.updatedRevenueBalances, uniquingKeysWith: { lhs, _ in lhs }), updatedStarsBalance: self.updatedStarsBalance.merging(other.updatedStarsBalance, uniquingKeysWith: { lhs, _ in lhs }), updatedStarsRevenueStatus: self.updatedStarsRevenueStatus.merging(other.updatedStarsRevenueStatus, uniquingKeysWith: { lhs, _ in lhs }), sentScheduledMessageIds: sentScheduledMessageIds, updatedUpgradedStarGifts: self.updatedUpgradedStarGifts + other.updatedUpgradedStarGifts)
|
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, addedReactionEvents: self.addedReactionEvents + other.addedReactionEvents, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, deletedMessageIds: self.deletedMessageIds + other.deletedMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, updatedGroupCallParticipants: self.updatedGroupCallParticipants + other.updatedGroupCallParticipants, storyUpdates: self.storyUpdates + other.storyUpdates, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, dismissBotWebViews: self.dismissBotWebViews + other.dismissBotWebViews, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated, updatedIncomingThreadReadStates: self.updatedIncomingThreadReadStates.merging(other.updatedIncomingThreadReadStates, uniquingKeysWith: { lhs, _ in lhs }), updateConfig: updateConfig, isPremiumUpdated: isPremiumUpdated, updatedRevenueBalances: self.updatedRevenueBalances.merging(other.updatedRevenueBalances, uniquingKeysWith: { lhs, _ in lhs }), updatedStarsBalance: self.updatedStarsBalance.merging(other.updatedStarsBalance, uniquingKeysWith: { lhs, _ in lhs }), updatedStarsRevenueStatus: self.updatedStarsRevenueStatus.merging(other.updatedStarsRevenueStatus, uniquingKeysWith: { lhs, _ in lhs }), sentScheduledMessageIds: sentScheduledMessageIds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
|||||||
return TelegramMediaAction(action: .paymentRefunded(peerId: peer.peerId, currency: currency, totalAmount: totalAmount, payload: payload?.makeData(), transactionId: transactionId))
|
return TelegramMediaAction(action: .paymentRefunded(peerId: peer.peerId, currency: currency, totalAmount: totalAmount, payload: payload?.makeData(), transactionId: transactionId))
|
||||||
case let .messageActionPrizeStars(flags, stars, transactionId, boostPeer, giveawayMsgId):
|
case let .messageActionPrizeStars(flags, stars, transactionId, boostPeer, giveawayMsgId):
|
||||||
return TelegramMediaAction(action: .prizeStars(amount: stars, isUnclaimed: (flags & (1 << 2)) != 0, boostPeerId: boostPeer.peerId, transactionId: transactionId, giveawayMessageId: MessageId(peerId: boostPeer.peerId, namespace: Namespaces.Message.Cloud, id: giveawayMsgId)))
|
return TelegramMediaAction(action: .prizeStars(amount: stars, isUnclaimed: (flags & (1 << 2)) != 0, boostPeerId: boostPeer.peerId, transactionId: transactionId, giveawayMessageId: MessageId(peerId: boostPeer.peerId, namespace: Namespaces.Message.Cloud, id: giveawayMsgId)))
|
||||||
case let .messageActionStarGift(flags, apiGift, message, convertStars, upgradeStars):
|
case let .messageActionStarGift(flags, apiGift, message, convertStars, _, upgradeStars):
|
||||||
let text: String?
|
let text: String?
|
||||||
let entities: [MessageTextEntity]?
|
let entities: [MessageTextEntity]?
|
||||||
switch message {
|
switch message {
|
||||||
@ -185,12 +185,12 @@ func telegramMediaActionFromApiAction(_ action: Api.MessageAction) -> TelegramMe
|
|||||||
guard let gift = StarGift(apiStarGift: apiGift) else {
|
guard let gift = StarGift(apiStarGift: apiGift) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, upgradeStars: upgradeStars))
|
return TelegramMediaAction(action: .starGift(gift: gift, convertStars: convertStars, text: text, entities: entities, nameHidden: (flags & (1 << 0)) != 0, savedToProfile: (flags & (1 << 2)) != 0, converted: (flags & (1 << 3)) != 0, upgraded: (flags & (1 << 5)) != 0, canUpgrade: (flags & (1 << 10)) != 0, upgradeStars: upgradeStars, isRefunded: (flags & (1 << 9)) != 0))
|
||||||
case let .messageActionStarGiftUnique(flags, apiGift, canExportAt, transferStars):
|
case let .messageActionStarGiftUnique(flags, apiGift, canExportAt, transferStars):
|
||||||
guard let gift = StarGift(apiStarGift: apiGift) else {
|
guard let gift = StarGift(apiStarGift: apiGift) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return TelegramMediaAction(action: .starGiftUnique(gift: gift, isUpgrade: (flags & (1 << 0)) != 0, isTransferred: (flags & (1 << 1)) != 0, savedToProfile: (flags & (1 << 2)) != 0, canExportDate: canExportAt, transferStars: transferStars))
|
return TelegramMediaAction(action: .starGiftUnique(gift: gift, isUpgrade: (flags & (1 << 0)) != 0, isTransferred: (flags & (1 << 1)) != 0, savedToProfile: (flags & (1 << 2)) != 0, canExportDate: canExportAt, transferStars: transferStars, isRefunded: (flags & (1 << 5)) != 0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3282,7 +3282,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
|||||||
var currentAddQuickReplyMessages: OptimizeAddMessagesState?
|
var currentAddQuickReplyMessages: OptimizeAddMessagesState?
|
||||||
for operation in operations {
|
for operation in operations {
|
||||||
switch operation {
|
switch operation {
|
||||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder, .UpdateReadThread, .UpdateMessagesPinned, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateWallpaper, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsAreAnonymousByDefault, .UpdateUpgradedStarGift:
|
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .UpdatePinnedSavedItemIds, .UpdatePinnedTopic, .UpdatePinnedTopicOrder, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateMessageForwardsCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder, .UpdateReadThread, .UpdateMessagesPinned, .UpdateGroupCallParticipants, .UpdateGroupCall, .UpdateAutoremoveTimeout, .UpdateAttachMenuBots, .UpdateAudioTranscription, .UpdateConfig, .UpdateExtendedMedia, .ResetForumTopic, .UpdateStory, .UpdateReadStories, .UpdateStoryStealthMode, .UpdateStorySentReaction, .UpdateNewAuthorization, .UpdateWallpaper, .UpdateRevenueBalances, .UpdateStarsBalance, .UpdateStarsRevenueStatus, .UpdateStarsReactionsAreAnonymousByDefault:
|
||||||
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
||||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||||
}
|
}
|
||||||
@ -3421,7 +3421,6 @@ func replayFinalState(
|
|||||||
var updatedStarsBalance: [PeerId: StarsAmount] = [:]
|
var updatedStarsBalance: [PeerId: StarsAmount] = [:]
|
||||||
var updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:]
|
var updatedStarsRevenueStatus: [PeerId: StarsRevenueStats.Balances] = [:]
|
||||||
var updatedStarsReactionsAreAnonymousByDefault: Bool?
|
var updatedStarsReactionsAreAnonymousByDefault: Bool?
|
||||||
var updatedUpgradedStarGifts: [(ProfileGiftsContext.State.StarGift, ProfileGiftsContext.State.StarGift)] = []
|
|
||||||
|
|
||||||
var holesFromPreviousStateMessageIds: [MessageId] = []
|
var holesFromPreviousStateMessageIds: [MessageId] = []
|
||||||
var clearHolesFromPreviousStateForChannelMessagesWithPts: [PeerIdAndMessageNamespace: Int32] = [:]
|
var clearHolesFromPreviousStateForChannelMessagesWithPts: [PeerIdAndMessageNamespace: Int32] = [:]
|
||||||
@ -4856,10 +4855,6 @@ func replayFinalState(
|
|||||||
updatedStarsRevenueStatus[peerId] = status
|
updatedStarsRevenueStatus[peerId] = status
|
||||||
case let .UpdateStarsReactionsAreAnonymousByDefault(value):
|
case let .UpdateStarsReactionsAreAnonymousByDefault(value):
|
||||||
updatedStarsReactionsAreAnonymousByDefault = value
|
updatedStarsReactionsAreAnonymousByDefault = value
|
||||||
case let .UpdateUpgradedStarGift(from, to):
|
|
||||||
if let fromGift = ProfileGiftsContext.State.StarGift(apiUserStarGift: from, transaction: transaction), let toGift = ProfileGiftsContext.State.StarGift(apiUserStarGift: to, transaction: transaction) {
|
|
||||||
updatedUpgradedStarGifts.append((fromGift, toGift))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5381,7 +5376,6 @@ func replayFinalState(
|
|||||||
updatedRevenueBalances: updatedRevenueBalances,
|
updatedRevenueBalances: updatedRevenueBalances,
|
||||||
updatedStarsBalance: updatedStarsBalance,
|
updatedStarsBalance: updatedStarsBalance,
|
||||||
updatedStarsRevenueStatus: updatedStarsRevenueStatus,
|
updatedStarsRevenueStatus: updatedStarsRevenueStatus,
|
||||||
updatedUpgradedStarGifts: updatedUpgradedStarGifts,
|
|
||||||
sentScheduledMessageIds: finalState.state.sentScheduledMessageIds
|
sentScheduledMessageIds: finalState.state.sentScheduledMessageIds
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -56,10 +56,6 @@ private final class UpdatedStarsRevenueStatusSubscriberContext {
|
|||||||
let subscribers = Bag<([PeerId: StarsRevenueStats.Balances]) -> Void>()
|
let subscribers = Bag<([PeerId: StarsRevenueStats.Balances]) -> Void>()
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class UpgradedStarGiftsSubscriberContext {
|
|
||||||
let subscribers = Bag<([(ProfileGiftsContext.State.StarGift, ProfileGiftsContext.State.StarGift)]) -> Void>()
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum DeletedMessageId: Hashable {
|
public enum DeletedMessageId: Hashable {
|
||||||
case global(Int32)
|
case global(Int32)
|
||||||
case messageId(MessageId)
|
case messageId(MessageId)
|
||||||
@ -350,7 +346,6 @@ public final class AccountStateManager {
|
|||||||
private var updatedRevenueBalancesContext = UpdatedRevenueBalancesSubscriberContext()
|
private var updatedRevenueBalancesContext = UpdatedRevenueBalancesSubscriberContext()
|
||||||
private var updatedStarsBalanceContext = UpdatedStarsBalanceSubscriberContext()
|
private var updatedStarsBalanceContext = UpdatedStarsBalanceSubscriberContext()
|
||||||
private var updatedStarsRevenueStatusContext = UpdatedStarsRevenueStatusSubscriberContext()
|
private var updatedStarsRevenueStatusContext = UpdatedStarsRevenueStatusSubscriberContext()
|
||||||
private var upgradedStarGiftsContext = UpgradedStarGiftsSubscriberContext()
|
|
||||||
|
|
||||||
private let delayNotificatonsUntil = Atomic<Int32?>(value: nil)
|
private let delayNotificatonsUntil = Atomic<Int32?>(value: nil)
|
||||||
private let appliedMaxMessageIdPromise = Promise<Int32?>(nil)
|
private let appliedMaxMessageIdPromise = Promise<Int32?>(nil)
|
||||||
@ -1113,9 +1108,6 @@ public final class AccountStateManager {
|
|||||||
if !events.updatedStarsRevenueStatus.isEmpty {
|
if !events.updatedStarsRevenueStatus.isEmpty {
|
||||||
strongSelf.notifyUpdatedStarsRevenueStatus(events.updatedStarsRevenueStatus)
|
strongSelf.notifyUpdatedStarsRevenueStatus(events.updatedStarsRevenueStatus)
|
||||||
}
|
}
|
||||||
if !events.updatedUpgradedStarGifts.isEmpty {
|
|
||||||
strongSelf.notifyUpgradedStarGifts(events.updatedUpgradedStarGifts)
|
|
||||||
}
|
|
||||||
if !events.updatedCalls.isEmpty {
|
if !events.updatedCalls.isEmpty {
|
||||||
for call in events.updatedCalls {
|
for call in events.updatedCalls {
|
||||||
strongSelf.callSessionManager?.updateSession(call, completion: { _ in })
|
strongSelf.callSessionManager?.updateSession(call, completion: { _ in })
|
||||||
@ -1775,33 +1767,6 @@ public final class AccountStateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func upgradedStarGifts() -> Signal<[(ProfileGiftsContext.State.StarGift, ProfileGiftsContext.State.StarGift)], NoError> {
|
|
||||||
let queue = self.queue
|
|
||||||
return Signal { [weak self] subscriber in
|
|
||||||
let disposable = MetaDisposable()
|
|
||||||
queue.async {
|
|
||||||
if let strongSelf = self {
|
|
||||||
let index = strongSelf.upgradedStarGiftsContext.subscribers.add({ upgradedGifts in
|
|
||||||
subscriber.putNext(upgradedGifts)
|
|
||||||
})
|
|
||||||
|
|
||||||
disposable.set(ActionDisposable {
|
|
||||||
if let strongSelf = self {
|
|
||||||
strongSelf.upgradedStarGiftsContext.subscribers.remove(index)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return disposable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func notifyUpgradedStarGifts(_ upgradedStarGifts: [(ProfileGiftsContext.State.StarGift, ProfileGiftsContext.State.StarGift)]) {
|
|
||||||
for subscriber in self.upgradedStarGiftsContext.subscribers.copyItems() {
|
|
||||||
subscriber(upgradedStarGifts)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func notifyDeletedMessages(messageIds: [MessageId]) {
|
func notifyDeletedMessages(messageIds: [MessageId]) {
|
||||||
self.deletedMessagesPipe.putNext(messageIds.map { .messageId($0) })
|
self.deletedMessagesPipe.putNext(messageIds.map { .messageId($0) })
|
||||||
}
|
}
|
||||||
@ -2143,12 +2108,6 @@ public final class AccountStateManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func upgradedStarGifts() -> Signal<[(ProfileGiftsContext.State.StarGift, ProfileGiftsContext.State.StarGift)], NoError> {
|
|
||||||
return self.impl.signalWith { impl, subscriber in
|
|
||||||
return impl.upgradedStarGifts().start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func addCustomOperation<T, E>(_ f: Signal<T, E>) -> Signal<T, E> {
|
func addCustomOperation<T, E>(_ f: Signal<T, E>) -> Signal<T, E> {
|
||||||
return self.impl.signalWith { impl, subscriber in
|
return self.impl.signalWith { impl, subscriber in
|
||||||
return impl.addCustomOperation(f).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
|
return impl.addCustomOperation(f).start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
|
||||||
|
@ -137,6 +137,7 @@ public struct Namespaces {
|
|||||||
public static let recommendedApps: Int8 = 40
|
public static let recommendedApps: Int8 = 40
|
||||||
public static let starsReactionDefaultToPrivate: Int8 = 41
|
public static let starsReactionDefaultToPrivate: Int8 = 41
|
||||||
public static let cachedPremiumGiftCodeOptions: Int8 = 42
|
public static let cachedPremiumGiftCodeOptions: Int8 = 42
|
||||||
|
public static let cachedProfileGifts: Int8 = 43
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct UnorderedItemList {
|
public struct UnorderedItemList {
|
||||||
|
@ -130,8 +130,8 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
case paymentRefunded(peerId: PeerId, currency: String, totalAmount: Int64, payload: Data?, transactionId: String)
|
case paymentRefunded(peerId: PeerId, currency: String, totalAmount: Int64, payload: Data?, transactionId: String)
|
||||||
case giftStars(currency: String, amount: Int64, count: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, transactionId: String?)
|
case giftStars(currency: String, amount: Int64, count: Int64, cryptoCurrency: String?, cryptoAmount: Int64?, transactionId: String?)
|
||||||
case prizeStars(amount: Int64, isUnclaimed: Bool, boostPeerId: PeerId?, transactionId: String?, giveawayMessageId: MessageId?)
|
case prizeStars(amount: Int64, isUnclaimed: Bool, boostPeerId: PeerId?, transactionId: String?, giveawayMessageId: MessageId?)
|
||||||
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, upgradeStars: Int64?)
|
case starGift(gift: StarGift, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, isRefunded: Bool)
|
||||||
case starGiftUnique(gift: StarGift, isUpgrade: Bool, isTransferred: Bool, savedToProfile: Bool, canExportDate: Int32?, transferStars: Int64?)
|
case starGiftUnique(gift: StarGift, isUpgrade: Bool, isTransferred: Bool, savedToProfile: Bool, canExportDate: Int32?, transferStars: Int64?, isRefunded: Bool)
|
||||||
|
|
||||||
public init(decoder: PostboxDecoder) {
|
public init(decoder: PostboxDecoder) {
|
||||||
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0)
|
||||||
@ -253,9 +253,9 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
}
|
}
|
||||||
self = .prizeStars(amount: decoder.decodeInt64ForKey("amount", orElse: 0), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: boostPeerId, transactionId: decoder.decodeOptionalStringForKey("transactionId"), giveawayMessageId: giveawayMessageId)
|
self = .prizeStars(amount: decoder.decodeInt64ForKey("amount", orElse: 0), isUnclaimed: decoder.decodeBoolForKey("unclaimed", orElse: false), boostPeerId: boostPeerId, transactionId: decoder.decodeOptionalStringForKey("transactionId"), giveawayMessageId: giveawayMessageId)
|
||||||
case 44:
|
case 44:
|
||||||
self = .starGift(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, convertStars: decoder.decodeOptionalInt64ForKey("convertStars"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"), nameHidden: decoder.decodeBoolForKey("nameHidden", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), converted: decoder.decodeBoolForKey("converted", orElse: false), upgraded: decoder.decodeBoolForKey("upgraded", orElse: false), upgradeStars: decoder.decodeOptionalInt64ForKey("upgradeStars"))
|
self = .starGift(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, convertStars: decoder.decodeOptionalInt64ForKey("convertStars"), text: decoder.decodeOptionalStringForKey("text"), entities: decoder.decodeOptionalObjectArrayWithDecoderForKey("entities"), nameHidden: decoder.decodeBoolForKey("nameHidden", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), converted: decoder.decodeBoolForKey("converted", orElse: false), upgraded: decoder.decodeBoolForKey("upgraded", orElse: false), canUpgrade: decoder.decodeBoolForKey("canUpgrade", orElse: false), upgradeStars: decoder.decodeOptionalInt64ForKey("upgradeStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false))
|
||||||
case 45:
|
case 45:
|
||||||
self = .starGiftUnique(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, isUpgrade: decoder.decodeBoolForKey("isUpgrade", orElse: false), isTransferred: decoder.decodeBoolForKey("isTransferred", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), canExportDate: decoder.decodeOptionalInt32ForKey("canExportDate"), transferStars: decoder.decodeOptionalInt64ForKey("transferStars"))
|
self = .starGiftUnique(gift: decoder.decodeObjectForKey("gift", decoder: { StarGift(decoder: $0) }) as! StarGift, isUpgrade: decoder.decodeBoolForKey("isUpgrade", orElse: false), isTransferred: decoder.decodeBoolForKey("isTransferred", orElse: false), savedToProfile: decoder.decodeBoolForKey("savedToProfile", orElse: false), canExportDate: decoder.decodeOptionalInt32ForKey("canExportDate"), transferStars: decoder.decodeOptionalInt64ForKey("transferStars"), isRefunded: decoder.decodeBoolForKey("isRefunded", orElse: false))
|
||||||
default:
|
default:
|
||||||
self = .unknown
|
self = .unknown
|
||||||
}
|
}
|
||||||
@ -548,7 +548,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "giveawayMsgId")
|
encoder.encodeNil(forKey: "giveawayMsgId")
|
||||||
}
|
}
|
||||||
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, upgradeStars):
|
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, isRefunded):
|
||||||
encoder.encodeInt32(44, forKey: "_rawValue")
|
encoder.encodeInt32(44, forKey: "_rawValue")
|
||||||
encoder.encodeObject(gift, forKey: "gift")
|
encoder.encodeObject(gift, forKey: "gift")
|
||||||
if let convertStars {
|
if let convertStars {
|
||||||
@ -567,12 +567,14 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
encoder.encodeBool(savedToProfile, forKey: "savedToProfile")
|
encoder.encodeBool(savedToProfile, forKey: "savedToProfile")
|
||||||
encoder.encodeBool(converted, forKey: "converted")
|
encoder.encodeBool(converted, forKey: "converted")
|
||||||
encoder.encodeBool(upgraded, forKey: "upgraded")
|
encoder.encodeBool(upgraded, forKey: "upgraded")
|
||||||
|
encoder.encodeBool(canUpgrade, forKey: "canUpgrade")
|
||||||
if let upgradeStars {
|
if let upgradeStars {
|
||||||
encoder.encodeInt64(upgradeStars, forKey: "upgradeStars")
|
encoder.encodeInt64(upgradeStars, forKey: "upgradeStars")
|
||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "upgradeStars")
|
encoder.encodeNil(forKey: "upgradeStars")
|
||||||
}
|
}
|
||||||
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars):
|
encoder.encodeBool(isRefunded, forKey: "isRefunded")
|
||||||
|
case let .starGiftUnique(gift, isUpgrade, isTransferred, savedToProfile, canExportDate, transferStars, isRefunded):
|
||||||
encoder.encodeInt32(45, forKey: "_rawValue")
|
encoder.encodeInt32(45, forKey: "_rawValue")
|
||||||
encoder.encodeObject(gift, forKey: "gift")
|
encoder.encodeObject(gift, forKey: "gift")
|
||||||
encoder.encodeBool(isUpgrade, forKey: "isUpgrade")
|
encoder.encodeBool(isUpgrade, forKey: "isUpgrade")
|
||||||
@ -588,6 +590,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable {
|
|||||||
} else {
|
} else {
|
||||||
encoder.encodeNil(forKey: "transferStars")
|
encoder.encodeNil(forKey: "transferStars")
|
||||||
}
|
}
|
||||||
|
encoder.encodeBool(isRefunded, forKey: "isRefunded")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,8 +707,17 @@ public enum UpgradeStarGiftError {
|
|||||||
case generic
|
case generic
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_upgradeStarGift(account: Account, prepaid: Bool, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
|
func _internal_upgradeStarGift(account: Account, formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
|
||||||
if prepaid {
|
if let formId {
|
||||||
|
let source: BotPaymentInvoiceSource = .starGiftUpgrade(keepOriginalInfo: keepOriginalInfo, messageId: messageId)
|
||||||
|
return _internal_sendStarsPaymentForm(account: account, formId: formId, source: source)
|
||||||
|
|> mapError { _ -> UpgradeStarGiftError in
|
||||||
|
return .generic
|
||||||
|
}
|
||||||
|
|> mapToSignal { _ in
|
||||||
|
return .complete()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
var flags: Int32 = 0
|
var flags: Int32 = 0
|
||||||
if keepOriginalInfo {
|
if keepOriginalInfo {
|
||||||
flags |= (1 << 0)
|
flags |= (1 << 0)
|
||||||
@ -719,57 +728,35 @@ func _internal_upgradeStarGift(account: Account, prepaid: Bool, messageId: Engin
|
|||||||
}
|
}
|
||||||
|> mapToSignal { updates in
|
|> mapToSignal { updates in
|
||||||
account.stateManager.addUpdates(updates)
|
account.stateManager.addUpdates(updates)
|
||||||
|
for update in updates.allUpdates {
|
||||||
return account.stateManager.upgradedStarGifts()
|
switch update {
|
||||||
|> castError(UpgradeStarGiftError.self)
|
case let .updateNewMessage(message, _, _):
|
||||||
|> take(until: { updates in
|
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: false) {
|
||||||
for update in updates {
|
for media in message.media {
|
||||||
if update.0.messageId == messageId {
|
if let action = media as? TelegramMediaAction, case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _) = action.action, case let .Id(messageId) = message.id {
|
||||||
return .init(passthrough: true, complete: true)
|
return .single(ProfileGiftsContext.State.StarGift(
|
||||||
}
|
gift: gift,
|
||||||
}
|
fromPeer: nil,
|
||||||
return .init(passthrough: false, complete: false)
|
date: message.timestamp,
|
||||||
})
|
text: nil,
|
||||||
|> mapToSignal { updates in
|
entities: nil,
|
||||||
for update in updates {
|
messageId: messageId,
|
||||||
if update.0.messageId == messageId {
|
nameHidden: false,
|
||||||
return .single(update.1)
|
savedToProfile: savedToProfile,
|
||||||
}
|
convertStars: nil,
|
||||||
}
|
canUpgrade: false,
|
||||||
return .complete()
|
canExportDate: canExportDate,
|
||||||
}
|
upgradeStars: nil,
|
||||||
}
|
transferStars: transferStars
|
||||||
} else {
|
))
|
||||||
let source: BotPaymentInvoiceSource = .starGiftUpgrade(keepOriginalInfo: keepOriginalInfo, messageId: messageId)
|
}
|
||||||
return _internal_fetchBotPaymentForm(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, source: source, themeParams: nil)
|
|
||||||
|> mapError { _ -> UpgradeStarGiftError in
|
|
||||||
return .generic
|
|
||||||
}
|
|
||||||
|> mapToSignal { paymentForm in
|
|
||||||
return _internal_sendStarsPaymentForm(account: account, formId: paymentForm.id, source: source)
|
|
||||||
|> mapError { _ -> UpgradeStarGiftError in
|
|
||||||
return .generic
|
|
||||||
}
|
|
||||||
|> mapToSignal { _ in
|
|
||||||
return account.stateManager.upgradedStarGifts()
|
|
||||||
|> castError(UpgradeStarGiftError.self)
|
|
||||||
|> take(until: { updates in
|
|
||||||
for update in updates {
|
|
||||||
if update.0.messageId == messageId {
|
|
||||||
return .init(passthrough: true, complete: true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return .init(passthrough: false, complete: false)
|
default:
|
||||||
})
|
break
|
||||||
|> mapToSignal { updates in
|
|
||||||
for update in updates {
|
|
||||||
if update.0.messageId == messageId {
|
|
||||||
return .single(update.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return .complete()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return .fail(.generic)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -791,7 +778,49 @@ func _internal_starGiftUpgradePreview(account: Account, giftId: Int64) -> Signal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var cachedAccountGifts: [EnginePeer.Id: [ProfileGiftsContext.State.StarGift]] = [:]
|
private final class CachedProfileGifts: Codable {
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case gifts
|
||||||
|
case count
|
||||||
|
}
|
||||||
|
|
||||||
|
var gifts: [ProfileGiftsContext.State.StarGift]
|
||||||
|
let count: Int32
|
||||||
|
|
||||||
|
init(gifts: [ProfileGiftsContext.State.StarGift], count: Int32) {
|
||||||
|
self.gifts = gifts
|
||||||
|
self.count = count
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.gifts = try container.decode([ProfileGiftsContext.State.StarGift].self, forKey: .gifts)
|
||||||
|
self.count = try container.decode(Int32.self, forKey: .count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.gifts, forKey: .gifts)
|
||||||
|
try container.encode(self.count, forKey: .count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func render(transaction: Transaction) {
|
||||||
|
for i in 0 ..< self.gifts.count {
|
||||||
|
let gift = self.gifts[i]
|
||||||
|
if gift.fromPeer == nil, let fromPeerId = gift._fromPeerId, let peer = transaction.getPeer(fromPeerId) {
|
||||||
|
self.gifts[i] = gift.withFromPeer(EnginePeer(peer))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func entryId(peerId: EnginePeer.Id) -> ItemCacheEntryId {
|
||||||
|
let cacheKey = ValueBoxKey(length: 8)
|
||||||
|
cacheKey.setInt64(0, value: peerId.toInt64())
|
||||||
|
return ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedProfileGifts, key: cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
private final class ProfileGiftsContextImpl {
|
private final class ProfileGiftsContextImpl {
|
||||||
private let queue: Queue
|
private let queue: Queue
|
||||||
@ -799,6 +828,7 @@ private final class ProfileGiftsContextImpl {
|
|||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
|
|
||||||
private let disposable = MetaDisposable()
|
private let disposable = MetaDisposable()
|
||||||
|
private let cacheDisposable = MetaDisposable()
|
||||||
private let actionDisposable = MetaDisposable()
|
private let actionDisposable = MetaDisposable()
|
||||||
|
|
||||||
private var gifts: [ProfileGiftsContext.State.StarGift] = []
|
private var gifts: [ProfileGiftsContext.State.StarGift] = []
|
||||||
@ -821,22 +851,37 @@ private final class ProfileGiftsContextImpl {
|
|||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.disposable.dispose()
|
self.disposable.dispose()
|
||||||
|
self.cacheDisposable.dispose()
|
||||||
self.actionDisposable.dispose()
|
self.actionDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadMore() {
|
func loadMore() {
|
||||||
|
let peerId = self.peerId
|
||||||
|
let accountPeerId = self.account.peerId
|
||||||
|
let network = self.account.network
|
||||||
|
let postbox = self.account.postbox
|
||||||
|
|
||||||
if case let .ready(true, initialNextOffset) = self.dataState {
|
if case let .ready(true, initialNextOffset) = self.dataState {
|
||||||
if self.gifts.isEmpty, self.peerId == self.account.peerId, let cachedGifts = cachedAccountGifts[self.peerId] {
|
if self.gifts.isEmpty, initialNextOffset == nil {
|
||||||
self.gifts = cachedGifts
|
self.cacheDisposable.set((self.account.postbox.transaction { transaction -> CachedProfileGifts? in
|
||||||
|
let cachedGifts = transaction.retrieveItemCacheEntry(id: entryId(peerId: peerId))?.get(CachedProfileGifts.self)
|
||||||
|
cachedGifts?.render(transaction: transaction)
|
||||||
|
return cachedGifts
|
||||||
|
} |> deliverOn(self.queue)).start(next: { [weak self] cachedGifts in
|
||||||
|
guard let self, let cachedGifts else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if case .loading = self.dataState {
|
||||||
|
self.gifts = cachedGifts.gifts
|
||||||
|
self.count = cachedGifts.count
|
||||||
|
self.pushState()
|
||||||
|
}
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
self.dataState = .loading
|
self.dataState = .loading
|
||||||
self.pushState()
|
self.pushState()
|
||||||
|
|
||||||
let peerId = self.peerId
|
|
||||||
let accountPeerId = self.account.peerId
|
|
||||||
let network = self.account.network
|
|
||||||
let postbox = self.account.postbox
|
|
||||||
let signal: Signal<([ProfileGiftsContext.State.StarGift], Int32, String?), NoError> = self.account.postbox.transaction { transaction -> Api.InputUser? in
|
let signal: Signal<([ProfileGiftsContext.State.StarGift], Int32, String?), NoError> = self.account.postbox.transaction { transaction -> Api.InputUser? in
|
||||||
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
return transaction.getPeer(peerId).flatMap(apiInputUser)
|
||||||
}
|
}
|
||||||
@ -871,9 +916,14 @@ private final class ProfileGiftsContextImpl {
|
|||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if initialNextOffset == nil, strongSelf.peerId == strongSelf.account.peerId {
|
if initialNextOffset == nil {
|
||||||
cachedAccountGifts[strongSelf.peerId] = gifts
|
|
||||||
strongSelf.gifts = gifts
|
strongSelf.gifts = gifts
|
||||||
|
|
||||||
|
strongSelf.cacheDisposable.set(strongSelf.account.postbox.transaction { transaction in
|
||||||
|
if let entry = CodableEntry(CachedProfileGifts(gifts: gifts, count: count)) {
|
||||||
|
transaction.putItemCacheEntry(id: entryId(peerId: peerId), entry: entry)
|
||||||
|
}
|
||||||
|
}.start())
|
||||||
} else {
|
} else {
|
||||||
for gift in gifts {
|
for gift in gifts {
|
||||||
strongSelf.gifts.append(gift)
|
strongSelf.gifts.append(gift)
|
||||||
@ -920,9 +970,14 @@ private final class ProfileGiftsContextImpl {
|
|||||||
self.pushState()
|
self.pushState()
|
||||||
}
|
}
|
||||||
|
|
||||||
func upgradeStarGift(prepaid: Bool, messageId: EngineMessage.Id, keepOriginalInfo: Bool) {
|
func upgradeStarGift(formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) {
|
||||||
self.actionDisposable.set(
|
self.actionDisposable.set(
|
||||||
_internal_upgradeStarGift(account: self.account, prepaid: prepaid, messageId: messageId, keepOriginalInfo: keepOriginalInfo).startStrict()
|
_internal_upgradeStarGift(account: self.account, formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo).startStrict(next: { [weak self] result in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = self
|
||||||
|
})
|
||||||
)
|
)
|
||||||
self.pushState()
|
self.pushState()
|
||||||
}
|
}
|
||||||
@ -935,7 +990,23 @@ private final class ProfileGiftsContextImpl {
|
|||||||
|
|
||||||
public final class ProfileGiftsContext {
|
public final class ProfileGiftsContext {
|
||||||
public struct State: Equatable {
|
public struct State: Equatable {
|
||||||
public struct StarGift: Equatable {
|
public struct StarGift: Equatable, Codable {
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case gift
|
||||||
|
case fromPeerId
|
||||||
|
case date
|
||||||
|
case text
|
||||||
|
case entities
|
||||||
|
case messageId
|
||||||
|
case nameHidden
|
||||||
|
case savedToProfile
|
||||||
|
case convertStars
|
||||||
|
case canUpgrade
|
||||||
|
case canExportDate
|
||||||
|
case upgradeStars
|
||||||
|
case transferStars
|
||||||
|
}
|
||||||
|
|
||||||
public let gift: TelegramCore.StarGift
|
public let gift: TelegramCore.StarGift
|
||||||
public let fromPeer: EnginePeer?
|
public let fromPeer: EnginePeer?
|
||||||
public let date: Int32
|
public let date: Int32
|
||||||
@ -950,6 +1021,76 @@ public final class ProfileGiftsContext {
|
|||||||
public let upgradeStars: Int64?
|
public let upgradeStars: Int64?
|
||||||
public let transferStars: Int64?
|
public let transferStars: Int64?
|
||||||
|
|
||||||
|
fileprivate let _fromPeerId: EnginePeer.Id?
|
||||||
|
|
||||||
|
public init (
|
||||||
|
gift: TelegramCore.StarGift,
|
||||||
|
fromPeer: EnginePeer?,
|
||||||
|
date: Int32,
|
||||||
|
text: String?,
|
||||||
|
entities: [MessageTextEntity]?,
|
||||||
|
messageId: EngineMessage.Id?,
|
||||||
|
nameHidden: Bool,
|
||||||
|
savedToProfile: Bool,
|
||||||
|
convertStars: Int64?,
|
||||||
|
canUpgrade: Bool,
|
||||||
|
canExportDate: Int32?,
|
||||||
|
upgradeStars: Int64?,
|
||||||
|
transferStars: Int64?
|
||||||
|
) {
|
||||||
|
self.gift = gift
|
||||||
|
self.fromPeer = fromPeer
|
||||||
|
self._fromPeerId = fromPeer?.id
|
||||||
|
self.date = date
|
||||||
|
self.text = text
|
||||||
|
self.entities = entities
|
||||||
|
self.messageId = messageId
|
||||||
|
self.nameHidden = nameHidden
|
||||||
|
self.savedToProfile = savedToProfile
|
||||||
|
self.convertStars = convertStars
|
||||||
|
self.canUpgrade = canUpgrade
|
||||||
|
self.canExportDate = canExportDate
|
||||||
|
self.upgradeStars = upgradeStars
|
||||||
|
self.transferStars = transferStars
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
self.gift = try container.decode(TelegramCore.StarGift.self, forKey: .gift)
|
||||||
|
self.fromPeer = nil
|
||||||
|
self._fromPeerId = try container.decodeIfPresent(EnginePeer.Id.self, forKey: .fromPeerId)
|
||||||
|
self.date = try container.decode(Int32.self, forKey: .date)
|
||||||
|
self.text = try container.decodeIfPresent(String.self, forKey: .text)
|
||||||
|
self.entities = try container.decodeIfPresent([MessageTextEntity].self, forKey: .entities)
|
||||||
|
self.messageId = try container.decodeIfPresent(EngineMessage.Id.self, forKey: .messageId)
|
||||||
|
self.nameHidden = try container.decode(Bool.self, forKey: .nameHidden)
|
||||||
|
self.savedToProfile = try container.decode(Bool.self, forKey: .savedToProfile)
|
||||||
|
self.convertStars = try container.decodeIfPresent(Int64.self, forKey: .convertStars)
|
||||||
|
self.canUpgrade = try container.decode(Bool.self, forKey: .canUpgrade)
|
||||||
|
self.canExportDate = try container.decodeIfPresent(Int32.self, forKey: .canExportDate)
|
||||||
|
self.upgradeStars = try container.decodeIfPresent(Int64.self, forKey: .upgradeStars)
|
||||||
|
self.transferStars = try container.decodeIfPresent(Int64.self, forKey: .transferStars)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
try container.encode(self.gift, forKey: .gift)
|
||||||
|
try container.encodeIfPresent(self.fromPeer?.id, forKey: .fromPeerId)
|
||||||
|
try container.encode(self.date, forKey: .date)
|
||||||
|
try container.encodeIfPresent(self.text, forKey: .text)
|
||||||
|
try container.encodeIfPresent(self.entities, forKey: .entities)
|
||||||
|
try container.encodeIfPresent(self.messageId, forKey: .messageId)
|
||||||
|
try container.encode(self.nameHidden, forKey: .nameHidden)
|
||||||
|
try container.encode(self.savedToProfile, forKey: .savedToProfile)
|
||||||
|
try container.encodeIfPresent(self.convertStars, forKey: .convertStars)
|
||||||
|
try container.encode(self.canUpgrade, forKey: .canUpgrade)
|
||||||
|
try container.encodeIfPresent(self.canExportDate, forKey: .canExportDate)
|
||||||
|
try container.encodeIfPresent(self.upgradeStars, forKey: .upgradeStars)
|
||||||
|
try container.encodeIfPresent(self.transferStars, forKey: .transferStars)
|
||||||
|
}
|
||||||
|
|
||||||
public func withSavedToProfile(_ savedToProfile: Bool) -> StarGift {
|
public func withSavedToProfile(_ savedToProfile: Bool) -> StarGift {
|
||||||
return StarGift(
|
return StarGift(
|
||||||
gift: self.gift,
|
gift: self.gift,
|
||||||
@ -967,6 +1108,24 @@ public final class ProfileGiftsContext {
|
|||||||
transferStars: self.transferStars
|
transferStars: self.transferStars
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fileprivate func withFromPeer(_ fromPeer: EnginePeer?) -> StarGift {
|
||||||
|
return StarGift(
|
||||||
|
gift: self.gift,
|
||||||
|
fromPeer: fromPeer,
|
||||||
|
date: self.date,
|
||||||
|
text: self.text,
|
||||||
|
entities: self.entities,
|
||||||
|
messageId: self.messageId,
|
||||||
|
nameHidden: self.nameHidden,
|
||||||
|
savedToProfile: savedToProfile,
|
||||||
|
convertStars: self.convertStars,
|
||||||
|
canUpgrade: self.canUpgrade,
|
||||||
|
canExportDate: self.canExportDate,
|
||||||
|
upgradeStars: self.upgradeStars,
|
||||||
|
transferStars: self.transferStars
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DataState: Equatable {
|
public enum DataState: Equatable {
|
||||||
@ -1027,9 +1186,9 @@ public final class ProfileGiftsContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func upgradeStarGift(prepaid: Bool, messageId: EngineMessage.Id, keepOriginalInfo: Bool) {
|
public func upgradeStarGift(formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) {
|
||||||
self.impl.with { impl in
|
self.impl.with { impl in
|
||||||
impl.upgradeStarGift(prepaid: prepaid, messageId: messageId, keepOriginalInfo: keepOriginalInfo)
|
impl.upgradeStarGift(formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,6 +1214,7 @@ extension ProfileGiftsContext.State.StarGift {
|
|||||||
} else {
|
} else {
|
||||||
self.fromPeer = nil
|
self.fromPeer = nil
|
||||||
}
|
}
|
||||||
|
self._fromPeerId = self.fromPeer?.id
|
||||||
self.date = date
|
self.date = date
|
||||||
|
|
||||||
if let message {
|
if let message {
|
||||||
@ -1081,7 +1241,7 @@ extension ProfileGiftsContext.State.StarGift {
|
|||||||
self.nameHidden = (flags & (1 << 0)) != 0
|
self.nameHidden = (flags & (1 << 0)) != 0
|
||||||
self.savedToProfile = (flags & (1 << 5)) == 0
|
self.savedToProfile = (flags & (1 << 5)) == 0
|
||||||
self.convertStars = convertStars
|
self.convertStars = convertStars
|
||||||
self.canUpgrade = (flags & (1 << 6)) != 0
|
self.canUpgrade = (flags & (1 << 10)) != 0
|
||||||
self.canExportDate = canExportDate
|
self.canExportDate = canExportDate
|
||||||
self.upgradeStars = upgradeStars
|
self.upgradeStars = upgradeStars
|
||||||
self.transferStars = transferStars
|
self.transferStars = transferStars
|
||||||
|
@ -125,8 +125,8 @@ public extension TelegramEngine {
|
|||||||
return _internal_transferStarGift(account: self.account, prepaid: prepaid, messageId: messageId, peerId: peerId)
|
return _internal_transferStarGift(account: self.account, prepaid: prepaid, messageId: messageId, peerId: peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func upgradeStarGift(prepaid: Bool, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
|
public func upgradeStarGift(formId: Int64?, messageId: EngineMessage.Id, keepOriginalInfo: Bool) -> Signal<ProfileGiftsContext.State.StarGift, UpgradeStarGiftError> {
|
||||||
return _internal_upgradeStarGift(account: self.account, prepaid: prepaid, messageId: messageId, keepOriginalInfo: keepOriginalInfo)
|
return _internal_upgradeStarGift(account: self.account, formId: formId, messageId: messageId, keepOriginalInfo: keepOriginalInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func starGiftUpgradePreview(giftId: Int64) -> Signal<[StarGift.UniqueGift.Attribute], NoError> {
|
public func starGiftUpgradePreview(giftId: Int64) -> Signal<[StarGift.UniqueGift.Attribute], NoError> {
|
||||||
|
@ -1066,7 +1066,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
attributedString = mutableString
|
attributedString = mutableString
|
||||||
case .prizeStars:
|
case .prizeStars:
|
||||||
attributedString = NSAttributedString(string: strings.Notification_StarsPrize, font: titleFont, textColor: primaryTextColor)
|
attributedString = NSAttributedString(string: strings.Notification_StarsPrize, font: titleFont, textColor: primaryTextColor)
|
||||||
case let .starGift(gift, _, text, entities, _, _, _, _, _):
|
case let .starGift(gift, _, text, entities, _, _, _, _, _, upgradeStars, _):
|
||||||
if !forAdditionalServiceMessage {
|
if !forAdditionalServiceMessage {
|
||||||
if let text {
|
if let text {
|
||||||
let mutableAttributedString = NSMutableAttributedString(attributedString: stringWithAppliedEntities(text, entities: entities ?? [], baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false, message: message._asMessage()))
|
let mutableAttributedString = NSMutableAttributedString(attributedString: stringWithAppliedEntities(text, entities: entities ?? [], baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: titleFont, linkFont: titleBoldFont, boldFont: titleBoldFont, italicFont: titleFont, boldItalicFont: titleBoldFont, fixedFont: titleFont, blockQuoteFont: titleFont, underlineLinks: false, message: message._asMessage()))
|
||||||
@ -1075,7 +1075,11 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
attributedString = NSAttributedString(string: strings.Notification_Gift, font: titleFont, textColor: primaryTextColor)
|
attributedString = NSAttributedString(string: strings.Notification_Gift, font: titleFont, textColor: primaryTextColor)
|
||||||
}
|
}
|
||||||
} else if case let .generic(gift) = gift {
|
} else if case let .generic(gift) = gift {
|
||||||
let starsPrice = strings.Notification_StarsGift_Stars(Int32(gift.price))
|
var finalPrice = gift.price
|
||||||
|
if let upgradeStars {
|
||||||
|
finalPrice += upgradeStars
|
||||||
|
}
|
||||||
|
let starsPrice = strings.Notification_StarsGift_Stars(Int32(finalPrice))
|
||||||
var authorName = compactAuthorName
|
var authorName = compactAuthorName
|
||||||
var peerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)]
|
var peerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)]
|
||||||
if message.id.peerId.namespace == Namespaces.Peer.CloudUser && message.id.peerId.id._internalGetInt64Value() == 777000 {
|
if message.id.peerId.namespace == Namespaces.Peer.CloudUser && message.id.peerId.id._internalGetInt64Value() == 777000 {
|
||||||
@ -1090,7 +1094,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
|
|||||||
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Sent(authorName, starsPrice)._tuple, body: bodyAttributes, argumentAttributes: attributes)
|
attributedString = addAttributesToStringWithRanges(strings.Notification_StarsGift_Sent(authorName, starsPrice)._tuple, body: bodyAttributes, argumentAttributes: attributes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .starGiftUnique(gift, isUpgrade, isTransferred, _, _, _):
|
case let .starGiftUnique(gift, isUpgrade, isTransferred, _, _, _, _):
|
||||||
if case let .unique(gift) = gift {
|
if case let .unique(gift) = gift {
|
||||||
if !forAdditionalServiceMessage {
|
if !forAdditionalServiceMessage {
|
||||||
attributedString = NSAttributedString(string: "\(gift.title) #\(gift.number)", font: titleFont, textColor: primaryTextColor)
|
attributedString = NSAttributedString(string: "\(gift.title) #\(gift.number)", font: titleFont, textColor: primaryTextColor)
|
||||||
|
@ -32,6 +32,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
|
"//submodules/TelegramUI/Components/Chat/ChatMessageItemCommon",
|
||||||
"//submodules/TelegramUI/Components/TextNodeWithEntities",
|
"//submodules/TelegramUI/Components/TextNodeWithEntities",
|
||||||
"//submodules/InvisibleInkDustNode",
|
"//submodules/InvisibleInkDustNode",
|
||||||
|
"//submodules/TelegramUI/Components/PeerInfo/PeerInfoCoverComponent",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -3,6 +3,7 @@ import UIKit
|
|||||||
import AsyncDisplayKit
|
import AsyncDisplayKit
|
||||||
import Display
|
import Display
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
|
import ComponentFlow
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import AccountContext
|
import AccountContext
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
@ -22,6 +23,7 @@ import ChatMessageBubbleContentNode
|
|||||||
import ChatMessageItemCommon
|
import ChatMessageItemCommon
|
||||||
import TextNodeWithEntities
|
import TextNodeWithEntities
|
||||||
import InvisibleInkDustNode
|
import InvisibleInkDustNode
|
||||||
|
import PeerInfoCoverComponent
|
||||||
|
|
||||||
private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id) -> NSAttributedString? {
|
private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id) -> NSAttributedString? {
|
||||||
return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: false, forForumOverview: false, forAdditionalServiceMessage: true)
|
return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: false, forForumOverview: false, forAdditionalServiceMessage: true)
|
||||||
@ -33,6 +35,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
private let backgroundMaskNode: ASImageNode
|
private let backgroundMaskNode: ASImageNode
|
||||||
private var linkHighlightingNode: LinkHighlightingNode?
|
private var linkHighlightingNode: LinkHighlightingNode?
|
||||||
|
|
||||||
|
private let patternView = ComponentView<Empty>()
|
||||||
private let mediaBackgroundMaskNode: ASImageNode
|
private let mediaBackgroundMaskNode: ASImageNode
|
||||||
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?
|
private var mediaBackgroundContent: WallpaperBubbleBackgroundNode?
|
||||||
private let titleNode: TextNode
|
private let titleNode: TextNode
|
||||||
@ -43,6 +46,13 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
private let placeholderNode: StickerShimmerEffectNode
|
private let placeholderNode: StickerShimmerEffectNode
|
||||||
private let animationNode: AnimatedStickerNode
|
private let animationNode: AnimatedStickerNode
|
||||||
|
|
||||||
|
private let modelTitleTextNode: TextNode
|
||||||
|
private let modelValueTextNode: TextNode
|
||||||
|
private let backdropTitleTextNode: TextNode
|
||||||
|
private let backdropValueTextNode: TextNode
|
||||||
|
private let symbolTitleTextNode: TextNode
|
||||||
|
private let symbolValueTextNode: TextNode
|
||||||
|
|
||||||
private let ribbonBackgroundNode: ASImageNode
|
private let ribbonBackgroundNode: ASImageNode
|
||||||
private let ribbonTextNode: TextNode
|
private let ribbonTextNode: TextNode
|
||||||
|
|
||||||
@ -50,6 +60,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
private let buttonNode: HighlightTrackingButtonNode
|
private let buttonNode: HighlightTrackingButtonNode
|
||||||
private let buttonStarsNode: PremiumStarsNode
|
private let buttonStarsNode: PremiumStarsNode
|
||||||
private let buttonTitleNode: TextNode
|
private let buttonTitleNode: TextNode
|
||||||
|
private let buttonIconNode: ASImageNode
|
||||||
|
|
||||||
private let moreTextNode: TextNode
|
private let moreTextNode: TextNode
|
||||||
|
|
||||||
@ -120,6 +131,25 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
self.textClippingNode = ASDisplayNode()
|
self.textClippingNode = ASDisplayNode()
|
||||||
self.textClippingNode.clipsToBounds = true
|
self.textClippingNode.clipsToBounds = true
|
||||||
|
|
||||||
|
self.modelTitleTextNode = TextNode()
|
||||||
|
self.modelTitleTextNode.isUserInteractionEnabled = false
|
||||||
|
self.modelTitleTextNode.displaysAsynchronously = false
|
||||||
|
self.modelValueTextNode = TextNode()
|
||||||
|
self.modelValueTextNode.isUserInteractionEnabled = false
|
||||||
|
self.modelValueTextNode.displaysAsynchronously = false
|
||||||
|
self.backdropTitleTextNode = TextNode()
|
||||||
|
self.backdropTitleTextNode.isUserInteractionEnabled = false
|
||||||
|
self.backdropTitleTextNode.displaysAsynchronously = false
|
||||||
|
self.backdropValueTextNode = TextNode()
|
||||||
|
self.backdropValueTextNode.isUserInteractionEnabled = false
|
||||||
|
self.backdropValueTextNode.displaysAsynchronously = false
|
||||||
|
self.symbolTitleTextNode = TextNode()
|
||||||
|
self.symbolTitleTextNode.isUserInteractionEnabled = false
|
||||||
|
self.symbolTitleTextNode.displaysAsynchronously = false
|
||||||
|
self.symbolValueTextNode = TextNode()
|
||||||
|
self.symbolValueTextNode.isUserInteractionEnabled = false
|
||||||
|
self.symbolValueTextNode.displaysAsynchronously = false
|
||||||
|
|
||||||
self.buttonNode = HighlightTrackingButtonNode()
|
self.buttonNode = HighlightTrackingButtonNode()
|
||||||
self.buttonNode.clipsToBounds = true
|
self.buttonNode.clipsToBounds = true
|
||||||
self.buttonNode.cornerRadius = 17.0
|
self.buttonNode.cornerRadius = 17.0
|
||||||
@ -136,6 +166,10 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
self.buttonTitleNode.isUserInteractionEnabled = false
|
self.buttonTitleNode.isUserInteractionEnabled = false
|
||||||
self.buttonTitleNode.displaysAsynchronously = false
|
self.buttonTitleNode.displaysAsynchronously = false
|
||||||
|
|
||||||
|
self.buttonIconNode = ASImageNode()
|
||||||
|
self.buttonIconNode.displaysAsynchronously = false
|
||||||
|
self.buttonIconNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
self.ribbonBackgroundNode = ASImageNode()
|
self.ribbonBackgroundNode = ASImageNode()
|
||||||
self.ribbonBackgroundNode.displaysAsynchronously = false
|
self.ribbonBackgroundNode.displaysAsynchronously = false
|
||||||
|
|
||||||
@ -161,6 +195,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
self.addSubnode(self.buttonNode)
|
self.addSubnode(self.buttonNode)
|
||||||
self.buttonNode.addSubnode(self.buttonStarsNode)
|
self.buttonNode.addSubnode(self.buttonStarsNode)
|
||||||
self.buttonNode.addSubnode(self.buttonTitleNode)
|
self.buttonNode.addSubnode(self.buttonTitleNode)
|
||||||
|
self.buttonNode.addSubnode(self.buttonIconNode)
|
||||||
|
|
||||||
self.addSubnode(self.ribbonBackgroundNode)
|
self.addSubnode(self.ribbonBackgroundNode)
|
||||||
self.addSubnode(self.ribbonTextNode)
|
self.addSubnode(self.ribbonTextNode)
|
||||||
@ -293,6 +328,13 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
let makeMeasureTextLayout = TextNode.asyncLayout(nil)
|
let makeMeasureTextLayout = TextNode.asyncLayout(nil)
|
||||||
let makeMoreTextLayout = TextNode.asyncLayout(self.moreTextNode)
|
let makeMoreTextLayout = TextNode.asyncLayout(self.moreTextNode)
|
||||||
|
|
||||||
|
let makeModelTitleLayout = TextNode.asyncLayout(self.modelTitleTextNode)
|
||||||
|
let makeModelValueLayout = TextNode.asyncLayout(self.modelValueTextNode)
|
||||||
|
let makeBackdropTitleLayout = TextNode.asyncLayout(self.backdropTitleTextNode)
|
||||||
|
let makeBackdropValueLayout = TextNode.asyncLayout(self.backdropValueTextNode)
|
||||||
|
let makeSymbolTitleLayout = TextNode.asyncLayout(self.symbolTitleTextNode)
|
||||||
|
let makeSymbolValueLayout = TextNode.asyncLayout(self.symbolValueTextNode)
|
||||||
|
|
||||||
let cachedMaskBackgroundImage = self.cachedMaskBackgroundImage
|
let cachedMaskBackgroundImage = self.cachedMaskBackgroundImage
|
||||||
|
|
||||||
let currentIsExpanded = self.isExpanded
|
let currentIsExpanded = self.isExpanded
|
||||||
@ -303,7 +345,12 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
|
||||||
var giftSize = CGSize(width: 220.0, height: 240.0)
|
var giftSize = CGSize(width: 220.0, height: 240.0)
|
||||||
|
|
||||||
let incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
let incoming: Bool
|
||||||
|
if item.message.id.peerId == item.context.account.peerId && item.message.forwardInfo == nil {
|
||||||
|
incoming = true
|
||||||
|
} else {
|
||||||
|
incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||||
|
}
|
||||||
|
|
||||||
let attributedString = attributedServiceMessageString(theme: item.presentationData.theme, strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, message: EngineMessage(item.message), accountPeerId: item.context.account.peerId)
|
let attributedString = attributedServiceMessageString(theme: item.presentationData.theme, strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, message: EngineMessage(item.message), accountPeerId: item.context.account.peerId)
|
||||||
|
|
||||||
@ -314,12 +361,26 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
var animationFile: TelegramMediaFile?
|
var animationFile: TelegramMediaFile?
|
||||||
var title = item.presentationData.strings.Notification_PremiumGift_Title
|
var title = item.presentationData.strings.Notification_PremiumGift_Title
|
||||||
var text = ""
|
var text = ""
|
||||||
|
var subtitleColor = primaryTextColor
|
||||||
var entities: [MessageTextEntity] = []
|
var entities: [MessageTextEntity] = []
|
||||||
var buttonTitle = item.presentationData.strings.Notification_PremiumGift_View
|
var buttonTitle = item.presentationData.strings.Notification_PremiumGift_View
|
||||||
|
var buttonIcon: String?
|
||||||
var ribbonTitle = ""
|
var ribbonTitle = ""
|
||||||
var hasServiceMessage = true
|
var hasServiceMessage = true
|
||||||
var textSpacing: CGFloat = 0.0
|
var textSpacing: CGFloat = 0.0
|
||||||
var isStarGift = false
|
var isStarGift = false
|
||||||
|
|
||||||
|
var modelTitle: String?
|
||||||
|
var modelValue: String?
|
||||||
|
var backdropTitle: String?
|
||||||
|
var backdropValue: String?
|
||||||
|
var symbolTitle: String?
|
||||||
|
var symbolValue: String?
|
||||||
|
var uniqueBackgroundColor: UIColor?
|
||||||
|
var uniqueSecondBackgroundColor: UIColor?
|
||||||
|
var uniquePatternColor: UIColor?
|
||||||
|
var uniquePatternFile: TelegramMediaFile?
|
||||||
|
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
if let action = media as? TelegramMediaAction {
|
if let action = media as? TelegramMediaAction {
|
||||||
switch action.action {
|
switch action.action {
|
||||||
@ -406,7 +467,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
buttonTitle = item.presentationData.strings.Notification_PremiumPrize_View
|
buttonTitle = item.presentationData.strings.Notification_PremiumPrize_View
|
||||||
hasServiceMessage = false
|
hasServiceMessage = false
|
||||||
}
|
}
|
||||||
case let .starGift(gift, convertStars, giftText, giftEntities, _, savedToProfile, converted, _, _):
|
case let .starGift(gift, convertStars, giftText, giftEntities, _, savedToProfile, converted, upgraded, _, upgradeStars, isRefunded):
|
||||||
if case let .generic(gift) = gift {
|
if case let .generic(gift) = gift {
|
||||||
isStarGift = true
|
isStarGift = true
|
||||||
let authorName = item.message.author.flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
|
let authorName = item.message.author.flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
|
||||||
@ -415,7 +476,9 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
text = giftText
|
text = giftText
|
||||||
entities = giftEntities ?? []
|
entities = giftEntities ?? []
|
||||||
} else {
|
} else {
|
||||||
if incoming {
|
if isRefunded {
|
||||||
|
text = item.presentationData.strings.Notification_StarGift_Subtitle_Refunded
|
||||||
|
} else if incoming {
|
||||||
if converted {
|
if converted {
|
||||||
text = item.presentationData.strings.Notification_StarGift_Subtitle_Converted(item.presentationData.strings.Notification_StarGift_Subtitle_Converted_Stars(Int32(convertStars ?? 0))).string
|
text = item.presentationData.strings.Notification_StarGift_Subtitle_Converted(item.presentationData.strings.Notification_StarGift_Subtitle_Converted_Stars(Int32(convertStars ?? 0))).string
|
||||||
} else if savedToProfile {
|
} else if savedToProfile {
|
||||||
@ -461,26 +524,49 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
ribbonTitle = item.presentationData.strings.Notification_StarGift_OneOf(availabilityString).string
|
ribbonTitle = item.presentationData.strings.Notification_StarGift_OneOf(availabilityString).string
|
||||||
}
|
}
|
||||||
if incoming {
|
if incoming, let upgradeStars, upgradeStars > 0, !upgraded {
|
||||||
buttonTitle = item.presentationData.strings.Notification_StarGift_View
|
buttonTitle = item.presentationData.strings.Notification_StarGift_Unpack
|
||||||
|
buttonIcon = "Premium/GiftUnpack"
|
||||||
} else {
|
} else {
|
||||||
buttonTitle = ""
|
buttonTitle = item.presentationData.strings.Notification_StarGift_View
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .starGiftUnique(gift, _, _, _, _, _):
|
case let .starGiftUnique(gift, _, _, _, _, _, isRefunded):
|
||||||
if case let .unique(uniqueGift) = gift {
|
if case let .unique(uniqueGift) = gift {
|
||||||
isStarGift = true
|
isStarGift = true
|
||||||
let authorName = item.message.author.flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
|
let authorName = item.message.author.flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
|
||||||
title = item.presentationData.strings.Notification_StarGift_Title(authorName).string
|
title = item.presentationData.strings.Notification_StarGift_Title(authorName).string
|
||||||
|
text = "**\(uniqueGift.title) #\(uniqueGift.number)**"
|
||||||
|
ribbonTitle = item.presentationData.strings.Notification_StarGift_Gift
|
||||||
|
buttonTitle = item.presentationData.strings.Notification_StarGift_View
|
||||||
|
modelTitle = item.presentationData.strings.Notification_StarGift_Model
|
||||||
|
backdropTitle = item.presentationData.strings.Notification_StarGift_Backdrop
|
||||||
|
symbolTitle = item.presentationData.strings.Notification_StarGift_Symbol
|
||||||
|
|
||||||
for attribute in uniqueGift.attributes {
|
for attribute in uniqueGift.attributes {
|
||||||
if case let .model(_, file, _) = attribute {
|
switch attribute {
|
||||||
|
case let .model(name, file, _):
|
||||||
|
modelValue = name
|
||||||
animationFile = file
|
animationFile = file
|
||||||
|
case let .backdrop(name, innerColor, outerColor, patternColor, _, _):
|
||||||
|
uniqueBackgroundColor = UIColor(rgb: UInt32(bitPattern: outerColor))
|
||||||
|
uniqueSecondBackgroundColor = UIColor(rgb: UInt32(bitPattern: innerColor))
|
||||||
|
uniquePatternColor = UIColor(rgb: UInt32(bitPattern: patternColor))
|
||||||
|
backdropValue = name
|
||||||
|
subtitleColor = UIColor(rgb: UInt32(bitPattern: innerColor)).withMultiplied(hue: 1.0, saturation: 1.02, brightness: 1.25).mixedWith(UIColor.white, alpha: 0.3)
|
||||||
|
case let .pattern(name, file, _):
|
||||||
|
symbolValue = name
|
||||||
|
uniquePatternFile = file
|
||||||
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO:localize
|
} else if isRefunded, case let .generic(gift) = gift {
|
||||||
ribbonTitle = "gift"
|
isStarGift = true
|
||||||
buttonTitle = item.presentationData.strings.Notification_StarGift_View
|
let authorName = item.message.author.flatMap { EnginePeer($0) }?.compactDisplayTitle ?? ""
|
||||||
|
title = item.presentationData.strings.Notification_StarGift_Title(authorName).string
|
||||||
|
text = item.presentationData.strings.Notification_StarGift_Subtitle_Refunded
|
||||||
|
animationFile = gift.file
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
@ -510,9 +596,9 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
attributedText = stringWithAppliedEntities(text, entities: entities, baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: Font.regular(13.0), linkFont: Font.regular(13.0), boldFont: Font.semibold(13.0), italicFont: Font.italic(13.0), boldItalicFont: Font.semiboldItalic(13.0), fixedFont: Font.monospace(13.0), blockQuoteFont: Font.regular(13.0), message: nil)
|
attributedText = stringWithAppliedEntities(text, entities: entities, baseColor: primaryTextColor, linkColor: primaryTextColor, baseFont: Font.regular(13.0), linkFont: Font.regular(13.0), boldFont: Font.semibold(13.0), italicFont: Font.italic(13.0), boldItalicFont: Font.semiboldItalic(13.0), fixedFont: Font.monospace(13.0), blockQuoteFont: Font.regular(13.0), message: nil)
|
||||||
} else {
|
} else {
|
||||||
attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(
|
attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(
|
||||||
body: MarkdownAttributeSet(font: Font.regular(13.0), textColor: primaryTextColor),
|
body: MarkdownAttributeSet(font: Font.regular(13.0), textColor: subtitleColor),
|
||||||
bold: MarkdownAttributeSet(font: Font.semibold(13.0), textColor: primaryTextColor),
|
bold: MarkdownAttributeSet(font: Font.semibold(13.0), textColor: subtitleColor),
|
||||||
link: MarkdownAttributeSet(font: Font.regular(13.0), textColor: primaryTextColor),
|
link: MarkdownAttributeSet(font: Font.regular(13.0), textColor: subtitleColor),
|
||||||
linkAttribute: { url in
|
linkAttribute: { url in
|
||||||
return ("URL", url)
|
return ("URL", url)
|
||||||
}
|
}
|
||||||
@ -534,11 +620,56 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let infoConstrainedSize = CGSize(width: (giftSize.width - 32.0) * 0.7, height: CGFloat.greatestFiniteMagnitude)
|
||||||
|
let modelTitleLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||||
|
if let modelTitle {
|
||||||
|
modelTitleLayoutAndApply = makeModelTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: modelTitle, font: Font.regular(13.0), textColor: subtitleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: infoConstrainedSize, alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
} else {
|
||||||
|
modelTitleLayoutAndApply = nil
|
||||||
|
}
|
||||||
|
let modelValueLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||||
|
if let modelValue {
|
||||||
|
modelValueLayoutAndApply = makeModelValueLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: modelValue, font: Font.semibold(13.0), textColor: primaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: infoConstrainedSize, alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
} else {
|
||||||
|
modelValueLayoutAndApply = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let backdropTitleLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||||
|
if let backdropTitle {
|
||||||
|
backdropTitleLayoutAndApply = makeBackdropTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: backdropTitle, font: Font.regular(13.0), textColor: subtitleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: infoConstrainedSize, alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
} else {
|
||||||
|
backdropTitleLayoutAndApply = nil
|
||||||
|
}
|
||||||
|
let backdropValueLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||||
|
if let backdropValue {
|
||||||
|
backdropValueLayoutAndApply = makeBackdropValueLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: backdropValue, font: Font.semibold(13.0), textColor: primaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: infoConstrainedSize, alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
} else {
|
||||||
|
backdropValueLayoutAndApply = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let symbolTitleLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||||
|
if let symbolTitle {
|
||||||
|
symbolTitleLayoutAndApply = makeSymbolTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: symbolTitle, font: Font.regular(13.0), textColor: subtitleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: infoConstrainedSize, alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
} else {
|
||||||
|
symbolTitleLayoutAndApply = nil
|
||||||
|
}
|
||||||
|
let symbolValueLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||||
|
if let symbolValue {
|
||||||
|
symbolValueLayoutAndApply = makeSymbolValueLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: symbolValue, font: Font.semibold(13.0), textColor: primaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: infoConstrainedSize, alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
} else {
|
||||||
|
symbolValueLayoutAndApply = nil
|
||||||
|
}
|
||||||
|
|
||||||
let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: buttonTitle, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
let (buttonTitleLayout, buttonTitleApply) = makeButtonTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: buttonTitle, font: Font.semibold(15.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
let (ribbonTextLayout, ribbonTextApply) = makeRibbonTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: ribbonTitle, font: Font.semibold(11.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
let (ribbonTextLayout, ribbonTextApply) = makeRibbonTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: ribbonTitle, font: Font.semibold(11.0), textColor: primaryTextColor, paragraphAlignment: .center), backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: giftSize.width - 32.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
giftSize.height = titleLayout.size.height + textSpacing + clippedTextHeight + 164.0
|
giftSize.height = titleLayout.size.height + textSpacing + clippedTextHeight + 164.0
|
||||||
|
|
||||||
|
if let _ = modelTitle {
|
||||||
|
giftSize.height += 70.0
|
||||||
|
}
|
||||||
|
|
||||||
if !buttonTitle.isEmpty {
|
if !buttonTitle.isEmpty {
|
||||||
giftSize.height += 48.0
|
giftSize.height += 48.0
|
||||||
}
|
}
|
||||||
@ -614,6 +745,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
|
|
||||||
strongSelf.buttonNode.isHidden = buttonTitle.isEmpty
|
strongSelf.buttonNode.isHidden = buttonTitle.isEmpty
|
||||||
strongSelf.buttonTitleNode.isHidden = buttonTitle.isEmpty
|
strongSelf.buttonTitleNode.isHidden = buttonTitle.isEmpty
|
||||||
|
strongSelf.buttonIconNode.isHidden = buttonIcon == nil
|
||||||
|
|
||||||
if strongSelf.item == nil {
|
if strongSelf.item == nil {
|
||||||
strongSelf.animationNode.started = { [weak self] in
|
strongSelf.animationNode.started = { [weak self] in
|
||||||
@ -677,7 +809,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
let titleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - titleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 151.0), size: titleLayout.size)
|
let titleFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - titleLayout.size.width) / 2.0) , y: mediaBackgroundFrame.minY + 151.0), size: titleLayout.size)
|
||||||
strongSelf.titleNode.frame = titleFrame
|
strongSelf.titleNode.frame = titleFrame
|
||||||
|
|
||||||
let clippingTextFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0) , y: titleFrame.maxY + textSpacing), size: CGSize(width: subtitleLayout.size.width, height: clippedTextHeight))
|
let clippingTextFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - subtitleLayout.size.width) / 2.0), y: titleFrame.maxY + textSpacing), size: CGSize(width: subtitleLayout.size.width, height: clippedTextHeight))
|
||||||
|
|
||||||
let subtitleFrame = CGRect(origin: .zero, size: subtitleLayout.size)
|
let subtitleFrame = CGRect(origin: .zero, size: subtitleLayout.size)
|
||||||
strongSelf.subtitleNode.textNode.frame = subtitleFrame
|
strongSelf.subtitleNode.textNode.frame = subtitleFrame
|
||||||
@ -727,19 +859,97 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
strongSelf.dustNode = nil
|
strongSelf.dustNode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
let buttonSize = CGSize(width: buttonTitleLayout.size.width + 38.0, height: 34.0)
|
var middleX = mediaBackgroundFrame.width / 2.0
|
||||||
strongSelf.buttonTitleNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((buttonSize.width - buttonTitleLayout.size.width) / 2.0), y: 8.0), size: buttonTitleLayout.size)
|
if let (modelValueLayout, _) = modelValueLayoutAndApply, let (backdropValueLayout, _) = backdropValueLayoutAndApply, let (symbolValueLayout, _) = symbolValueLayoutAndApply {
|
||||||
|
let maxWidth = max(modelValueLayout.size.width, max(backdropValueLayout.size.width, symbolValueLayout.size.width))
|
||||||
|
middleX = min(mediaBackgroundFrame.width - maxWidth - 16.0, middleX)
|
||||||
|
}
|
||||||
|
|
||||||
animation.animator.updateFrame(layer: strongSelf.buttonNode.layer, frame: CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonSize.width) / 2.0), y: clippingTextFrame.maxY + 10.0), size: buttonSize), completion: nil)
|
let titleMaxX: CGFloat = mediaBackgroundFrame.minX + middleX - 2.0
|
||||||
|
let valueMinX: CGFloat = mediaBackgroundFrame.minX + middleX + 3.0
|
||||||
|
|
||||||
|
if let (modelTitleLayout, modelTitleApply) = modelTitleLayoutAndApply {
|
||||||
|
if strongSelf.modelTitleTextNode.supernode == nil {
|
||||||
|
strongSelf.addSubnode(strongSelf.modelTitleTextNode)
|
||||||
|
}
|
||||||
|
let _ = modelTitleApply()
|
||||||
|
strongSelf.modelTitleTextNode.frame = CGRect(origin: CGPoint(x: titleMaxX - modelTitleLayout.size.width, y: clippingTextFrame.maxY + 10.0), size: modelTitleLayout.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (modelValueLayout, modelValueApply) = modelValueLayoutAndApply {
|
||||||
|
if strongSelf.modelValueTextNode.supernode == nil {
|
||||||
|
strongSelf.addSubnode(strongSelf.modelValueTextNode)
|
||||||
|
}
|
||||||
|
let _ = modelValueApply()
|
||||||
|
strongSelf.modelValueTextNode.frame = CGRect(origin: CGPoint(x: valueMinX, y: clippingTextFrame.maxY + 10.0), size: modelValueLayout.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (backdropTitleLayout, backdropTitleApply) = backdropTitleLayoutAndApply {
|
||||||
|
if strongSelf.backdropTitleTextNode.supernode == nil {
|
||||||
|
strongSelf.addSubnode(strongSelf.backdropTitleTextNode)
|
||||||
|
}
|
||||||
|
let _ = backdropTitleApply()
|
||||||
|
strongSelf.backdropTitleTextNode.frame = CGRect(origin: CGPoint(x: titleMaxX - backdropTitleLayout.size.width, y: clippingTextFrame.maxY + 32.0), size: backdropTitleLayout.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (backdropValueLayout, backdropValueApply) = backdropValueLayoutAndApply {
|
||||||
|
if strongSelf.backdropValueTextNode.supernode == nil {
|
||||||
|
strongSelf.addSubnode(strongSelf.backdropValueTextNode)
|
||||||
|
}
|
||||||
|
let _ = backdropValueApply()
|
||||||
|
strongSelf.backdropValueTextNode.frame = CGRect(origin: CGPoint(x: valueMinX, y: clippingTextFrame.maxY + 32.0), size: backdropValueLayout.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (symbolTitleLayout, symbolTitleApply) = symbolTitleLayoutAndApply {
|
||||||
|
if strongSelf.symbolTitleTextNode.supernode == nil {
|
||||||
|
strongSelf.addSubnode(strongSelf.symbolTitleTextNode)
|
||||||
|
}
|
||||||
|
let _ = symbolTitleApply()
|
||||||
|
strongSelf.symbolTitleTextNode.frame = CGRect(origin: CGPoint(x: titleMaxX - symbolTitleLayout.size.width, y: clippingTextFrame.maxY + 54.0), size: symbolTitleLayout.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let (symbolValueLayout, symbolValueApply) = symbolValueLayoutAndApply {
|
||||||
|
if strongSelf.symbolValueTextNode.supernode == nil {
|
||||||
|
strongSelf.addSubnode(strongSelf.symbolValueTextNode)
|
||||||
|
}
|
||||||
|
let _ = symbolValueApply()
|
||||||
|
strongSelf.symbolValueTextNode.frame = CGRect(origin: CGPoint(x: valueMinX, y: clippingTextFrame.maxY + 54.0), size: symbolValueLayout.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buttonSize = CGSize(width: buttonTitleLayout.size.width + 38.0, height: 34.0)
|
||||||
|
var buttonOriginY = clippingTextFrame.maxY + 10.0
|
||||||
|
if modelTitleLayoutAndApply != nil {
|
||||||
|
buttonOriginY = clippingTextFrame.maxY + 80.0
|
||||||
|
}
|
||||||
|
if let buttonIcon {
|
||||||
|
buttonSize.width += 15.0
|
||||||
|
if strongSelf.buttonIconNode.image == nil {
|
||||||
|
strongSelf.buttonIconNode.image = generateTintedImage(image: UIImage(bundleImageName: buttonIcon), color: .white)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strongSelf.buttonTitleNode.frame = CGRect(origin: CGPoint(x: 19.0, y: 8.0), size: buttonTitleLayout.size)
|
||||||
|
strongSelf.buttonIconNode.frame = CGRect(origin: CGPoint(x: buttonSize.width - 30.0, y: 9.0), size: CGSize(width: 14.0, height: 14.0))
|
||||||
|
|
||||||
|
animation.animator.updateFrame(layer: strongSelf.buttonNode.layer, frame: CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - buttonSize.width) / 2.0), y: buttonOriginY), size: buttonSize), completion: nil)
|
||||||
strongSelf.buttonStarsNode.frame = CGRect(origin: .zero, size: buttonSize)
|
strongSelf.buttonStarsNode.frame = CGRect(origin: .zero, size: buttonSize)
|
||||||
|
|
||||||
if ribbonTextLayout.size.width > 0.0 {
|
if ribbonTextLayout.size.width > 0.0 {
|
||||||
if strongSelf.ribbonBackgroundNode.image == nil {
|
if strongSelf.ribbonBackgroundNode.image == nil {
|
||||||
let ribbonImage = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/GiftRibbon"), color: overlayColor)
|
if let uniqueBackgroundColor {
|
||||||
strongSelf.ribbonBackgroundNode.image = ribbonImage
|
let colors = [
|
||||||
|
uniqueBackgroundColor.withMultiplied(hue: 0.97, saturation: 1.45, brightness: 0.89),
|
||||||
|
uniqueBackgroundColor.withMultiplied(hue: 1.01, saturation: 1.22, brightness: 1.04)
|
||||||
|
]
|
||||||
|
strongSelf.ribbonBackgroundNode.image = generateGradientTintedImage(image: UIImage(bundleImageName: "Premium/GiftRibbon"), colors: colors, direction: .mirroredDiagonal)
|
||||||
|
} else {
|
||||||
|
strongSelf.ribbonBackgroundNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Message/GiftRibbon"), color: overlayColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let ribbonImage = strongSelf.ribbonBackgroundNode.image {
|
if let ribbonImage = strongSelf.ribbonBackgroundNode.image {
|
||||||
let ribbonFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.maxX - ribbonImage.size.width + 2.0, y: mediaBackgroundFrame.minY - 2.0), size: ribbonImage.size)
|
var ribbonFrame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.maxX - ribbonImage.size.width + 2.0, y: mediaBackgroundFrame.minY - 2.0), size: ribbonImage.size)
|
||||||
|
if let _ = uniqueBackgroundColor {
|
||||||
|
ribbonFrame = ribbonFrame.offsetBy(dx: -4.0, dy: 4.0)
|
||||||
|
}
|
||||||
strongSelf.ribbonBackgroundNode.frame = ribbonFrame
|
strongSelf.ribbonBackgroundNode.frame = ribbonFrame
|
||||||
|
|
||||||
strongSelf.ribbonTextNode.transform = CATransform3DMakeRotation(.pi / 4.0, 0.0, 0.0, 1.0)
|
strongSelf.ribbonTextNode.transform = CATransform3DMakeRotation(.pi / 4.0, 0.0, 0.0, 1.0)
|
||||||
@ -757,7 +967,7 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let backgroundContent = strongSelf.mediaBackgroundContent {
|
if let backgroundContent = strongSelf.mediaBackgroundContent {
|
||||||
if ribbonTextLayout.size.width > 0.0 {
|
if ribbonTextLayout.size.width > 0.0, uniqueBackgroundColor == nil {
|
||||||
let backgroundMaskFrame = mediaBackgroundFrame.insetBy(dx: -2.0, dy: -2.0)
|
let backgroundMaskFrame = mediaBackgroundFrame.insetBy(dx: -2.0, dy: -2.0)
|
||||||
backgroundContent.frame = backgroundMaskFrame
|
backgroundContent.frame = backgroundMaskFrame
|
||||||
animation.animator.updateFrame(layer: backgroundContent.layer, frame: backgroundMaskFrame, completion: nil)
|
animation.animator.updateFrame(layer: backgroundContent.layer, frame: backgroundMaskFrame, completion: nil)
|
||||||
@ -787,6 +997,36 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let uniqueBackgroundColor, let uniqueSecondBackgroundColor, let uniquePatternColor, let uniquePatternFile {
|
||||||
|
let patternInset: CGFloat = 4.0
|
||||||
|
let patternSize = CGSize(width: mediaBackgroundFrame.width - patternInset * 2.0, height: mediaBackgroundFrame.height - patternInset * 2.0)
|
||||||
|
let files: [Int64: TelegramMediaFile] = [uniquePatternFile.fileId.id: uniquePatternFile]
|
||||||
|
let _ = strongSelf.patternView.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: AnyComponent(PeerInfoCoverComponent(
|
||||||
|
context: item.context,
|
||||||
|
subject: .custom(uniqueBackgroundColor, uniqueSecondBackgroundColor, uniquePatternColor, uniquePatternFile.fileId.id),
|
||||||
|
files: files,
|
||||||
|
isDark: false,
|
||||||
|
avatarCenter: CGPoint(x: patternSize.width / 2.0, y: 106.0),
|
||||||
|
avatarScale: 1.0,
|
||||||
|
defaultHeight: patternSize.height,
|
||||||
|
avatarTransitionFraction: 0.0,
|
||||||
|
patternTransitionFraction: 0.0
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: patternSize
|
||||||
|
)
|
||||||
|
if let backgroundView = strongSelf.patternView.view {
|
||||||
|
if backgroundView.superview == nil {
|
||||||
|
backgroundView.layer.cornerRadius = 20.0
|
||||||
|
backgroundView.clipsToBounds = true
|
||||||
|
strongSelf.view.insertSubview(backgroundView, belowSubview: strongSelf.titleNode.view)
|
||||||
|
}
|
||||||
|
backgroundView.frame = CGRect(origin: .zero, size: patternSize).offsetBy(dx: mediaBackgroundFrame.minX + patternInset, dy: mediaBackgroundFrame.minY + patternInset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let baseBackgroundFrame = labelFrame.offsetBy(dx: 0.0, dy: -11.0)
|
let baseBackgroundFrame = labelFrame.offsetBy(dx: 0.0, dy: -11.0)
|
||||||
if let (offset, image) = backgroundMaskImage {
|
if let (offset, image) = backgroundMaskImage {
|
||||||
if strongSelf.backgroundNode == nil {
|
if strongSelf.backgroundNode == nil {
|
||||||
|
@ -909,7 +909,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
|||||||
var titleFrame: CGRect
|
var titleFrame: CGRect
|
||||||
if size.height > 40.0 {
|
if size.height > 40.0 {
|
||||||
var titleInsets: UIEdgeInsets = .zero
|
var titleInsets: UIEdgeInsets = .zero
|
||||||
if verifiedIconWidth > 0.0 {
|
if case .emojiStatus = self.titleVerifiedIcon, verifiedIconWidth > 0.0 {
|
||||||
titleInsets.left = verifiedIconWidth + 2.0
|
titleInsets.left = verifiedIconWidth + 2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -951,7 +951,18 @@ public final class ChatTitleView: UIView, NavigationBarTitleView {
|
|||||||
|
|
||||||
var nextIconX: CGFloat = titleFrame.width
|
var nextIconX: CGFloat = titleFrame.width
|
||||||
|
|
||||||
self.titleVerifiedIconView.frame = CGRect(origin: CGPoint(x: 0.0, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize)
|
var verifiedIconX: CGFloat
|
||||||
|
if case .emojiStatus = self.titleVerifiedIcon {
|
||||||
|
verifiedIconX = 0.0
|
||||||
|
} else {
|
||||||
|
verifiedIconX = nextIconX - titleVerifiedSize.width
|
||||||
|
}
|
||||||
|
|
||||||
|
self.titleVerifiedIconView.frame = CGRect(origin: CGPoint(x: verifiedIconX, y: floor((titleFrame.height - titleVerifiedSize.height) / 2.0)), size: titleVerifiedSize)
|
||||||
|
if case .emojiStatus = self.titleVerifiedIcon {
|
||||||
|
} else {
|
||||||
|
nextIconX -= titleVerifiedSize.width
|
||||||
|
}
|
||||||
|
|
||||||
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
|
self.titleCredibilityIconView.frame = CGRect(origin: CGPoint(x: nextIconX - titleCredibilitySize.width, y: floor((titleFrame.height - titleCredibilitySize.height) / 2.0)), size: titleCredibilitySize)
|
||||||
nextIconX -= titleCredibilitySize.width
|
nextIconX -= titleCredibilitySize.width
|
||||||
|
@ -26,6 +26,7 @@ swift_library(
|
|||||||
"//submodules/Components/ViewControllerComponent",
|
"//submodules/Components/ViewControllerComponent",
|
||||||
"//submodules/Components/BundleIconComponent",
|
"//submodules/Components/BundleIconComponent",
|
||||||
"//submodules/Components/MultilineTextComponent",
|
"//submodules/Components/MultilineTextComponent",
|
||||||
|
"//submodules/Components/MultilineTextWithEntitiesComponent",
|
||||||
"//submodules/Components/BalancedTextComponent",
|
"//submodules/Components/BalancedTextComponent",
|
||||||
"//submodules/TelegramUI/Components/ListSectionComponent",
|
"//submodules/TelegramUI/Components/ListSectionComponent",
|
||||||
"//submodules/TelegramUI/Components/ListActionItemComponent",
|
"//submodules/TelegramUI/Components/ListActionItemComponent",
|
||||||
@ -45,6 +46,7 @@ swift_library(
|
|||||||
"//submodules/InAppPurchaseManager",
|
"//submodules/InAppPurchaseManager",
|
||||||
"//submodules/Components/BlurredBackgroundComponent",
|
"//submodules/Components/BlurredBackgroundComponent",
|
||||||
"//submodules/ProgressNavigationButtonNode",
|
"//submodules/ProgressNavigationButtonNode",
|
||||||
|
"//submodules/TelegramUI/Components/Gifts/GiftViewScreen",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -143,6 +143,9 @@ final class ChatGiftPreviewItem: ListViewItem, ItemListItem, ListItemComponentAd
|
|||||||
if lhs.entities != rhs.entities {
|
if lhs.entities != rhs.entities {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.includeUpgrade != rhs.includeUpgrade {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,7 +227,7 @@ final class ChatGiftPreviewItemNode: ListViewItemNode {
|
|||||||
case let .starGift(gift):
|
case let .starGift(gift):
|
||||||
media = [
|
media = [
|
||||||
TelegramMediaAction(
|
TelegramMediaAction(
|
||||||
action: .starGift(gift: .generic(gift), convertStars: gift.convertStars, text: item.text, entities: item.entities, nameHidden: false, savedToProfile: false, converted: false, upgraded: false, upgradeStars: item.includeUpgrade ? 0 : gift.upgradeStars)
|
action: .starGift(gift: .generic(gift), convertStars: gift.convertStars, text: item.text, entities: item.entities, nameHidden: false, savedToProfile: false, converted: false, upgraded: false, canUpgrade: true, upgradeStars: item.includeUpgrade ? gift.upgradeStars : 0, isRefunded: false)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import AccountContext
|
|||||||
import ComponentFlow
|
import ComponentFlow
|
||||||
import ViewControllerComponent
|
import ViewControllerComponent
|
||||||
import MultilineTextComponent
|
import MultilineTextComponent
|
||||||
|
import MultilineTextWithEntitiesComponent
|
||||||
import BalancedTextComponent
|
import BalancedTextComponent
|
||||||
import ListSectionComponent
|
import ListSectionComponent
|
||||||
import ListActionItemComponent
|
import ListActionItemComponent
|
||||||
@ -32,6 +33,7 @@ import InAppPurchaseManager
|
|||||||
import BlurredBackgroundComponent
|
import BlurredBackgroundComponent
|
||||||
import ProgressNavigationButtonNode
|
import ProgressNavigationButtonNode
|
||||||
import Markdown
|
import Markdown
|
||||||
|
import GiftViewScreen
|
||||||
|
|
||||||
final class GiftSetupScreenComponent: Component {
|
final class GiftSetupScreenComponent: Component {
|
||||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
@ -131,6 +133,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private let optionsPromise = ValuePromise<[StarsTopUpOption]?>(nil)
|
private let optionsPromise = ValuePromise<[StarsTopUpOption]?>(nil)
|
||||||
|
private let previewPromise = Promise<[StarGift.UniqueGift.Attribute]?>(nil)
|
||||||
|
|
||||||
private var cachedChevronImage: (UIImage, PresentationTheme)?
|
private var cachedChevronImage: (UIImage, PresentationTheme)?
|
||||||
|
|
||||||
@ -578,7 +581,7 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if case .starGift = component.subject {
|
if case let .starGift(gift) = component.subject {
|
||||||
self.optionsDisposable = (component.context.engine.payments.starsTopUpOptions()
|
self.optionsDisposable = (component.context.engine.payments.starsTopUpOptions()
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] options in
|
|> deliverOnMainQueue).start(next: { [weak self] options in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -586,6 +589,13 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
self.options = options
|
self.options = options
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if let _ = gift.upgradeStars {
|
||||||
|
self.previewPromise.set(
|
||||||
|
component.context.engine.payments.starGiftUpgradePreview(giftId: gift.id)
|
||||||
|
|> map(Optional.init)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,6 +855,13 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
upgradeFooterText.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: upgradeFooterText.string))
|
upgradeFooterText.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: upgradeFooterText.string))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let upgradeAttributedText = NSMutableAttributedString(string: environment.strings.Gift_Send_Upgrade("#\(upgradeStars)").string, font: Font.regular(presentationData.listsFontSize.baseDisplaySize), textColor: environment.theme.list.itemPrimaryTextColor)
|
||||||
|
let range = (upgradeAttributedText.string as NSString).range(of: "#")
|
||||||
|
if range.location != NSNotFound {
|
||||||
|
upgradeAttributedText.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: range)
|
||||||
|
upgradeAttributedText.addAttribute(.baselineOffset, value: 1.0, range: range)
|
||||||
|
}
|
||||||
|
|
||||||
let upgradeSectionSize = self.upgradeSection.update(
|
let upgradeSectionSize = self.upgradeSection.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(ListSectionComponent(
|
component: AnyComponent(ListSectionComponent(
|
||||||
@ -852,20 +869,47 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
header: nil,
|
header: nil,
|
||||||
footer: AnyComponent(MultilineTextComponent(
|
footer: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(upgradeFooterText),
|
text: .plain(upgradeFooterText),
|
||||||
maximumNumberOfLines: 0
|
maximumNumberOfLines: 0,
|
||||||
|
highlightColor: environment.theme.list.itemAccentColor.withAlphaComponent(0.1),
|
||||||
|
highlightInset: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: -8.0),
|
||||||
|
highlightAction: { attributes in
|
||||||
|
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
|
||||||
|
return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tapAction: { [weak self] _, _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let _ = (self.previewPromise.get()
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] attributes in
|
||||||
|
guard let self, let component = self.component, let controller = self.environment?.controller(), let attributes else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let previewController = GiftViewScreen(
|
||||||
|
context: component.context,
|
||||||
|
subject: .upgradePreview(attributes, peerName)
|
||||||
|
)
|
||||||
|
controller.push(previewController)
|
||||||
|
})
|
||||||
|
}
|
||||||
)),
|
)),
|
||||||
items: [
|
items: [
|
||||||
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
|
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
title: AnyComponent(VStack([
|
title: AnyComponent(VStack([
|
||||||
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(MultilineTextComponent(
|
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(
|
||||||
text: .plain(NSAttributedString(
|
MultilineTextWithEntitiesComponent(
|
||||||
string: environment.strings.Gift_Send_Upgrade("\(upgradeStars)").string,
|
context: component.context,
|
||||||
font: Font.regular(presentationData.listsFontSize.baseDisplaySize),
|
animationCache: component.context.animationCache,
|
||||||
textColor: environment.theme.list.itemPrimaryTextColor
|
animationRenderer: component.context.animationRenderer,
|
||||||
)),
|
placeholderColor: environment.theme.list.mediaPlaceholderColor,
|
||||||
maximumNumberOfLines: 1
|
text: .plain(upgradeAttributedText)
|
||||||
))),
|
)
|
||||||
|
)),
|
||||||
], alignment: .left, spacing: 2.0)),
|
], alignment: .left, spacing: 2.0)),
|
||||||
accessory: .toggle(ListActionItemComponent.Toggle(style: .regular, isOn: self.includeUpgrade, action: { [weak self] _ in
|
accessory: .toggle(ListActionItemComponent.Toggle(style: .regular, isOn: self.includeUpgrade, action: { [weak self] _ in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
@ -982,7 +1026,11 @@ final class GiftSetupScreenComponent: Component {
|
|||||||
let amountString = product.price
|
let amountString = product.price
|
||||||
buttonString = "\(environment.strings.Gift_Send_Send) \(amountString)"
|
buttonString = "\(environment.strings.Gift_Send_Send) \(amountString)"
|
||||||
case let .starGift(starGift):
|
case let .starGift(starGift):
|
||||||
let amountString = presentationStringsFormattedNumber(Int32(starGift.price), presentationData.dateTimeFormat.groupingSeparator)
|
var finalPrice: Int64 = starGift.price
|
||||||
|
if self.includeUpgrade, let upgradePrice = starGift.upgradeStars {
|
||||||
|
finalPrice += upgradePrice
|
||||||
|
}
|
||||||
|
let amountString = presentationStringsFormattedNumber(Int32(finalPrice), presentationData.dateTimeFormat.groupingSeparator)
|
||||||
buttonString = "\(environment.strings.Gift_Send_Send) # \(amountString)"
|
buttonString = "\(environment.strings.Gift_Send_Send) # \(amountString)"
|
||||||
if let availability = starGift.availability, availability.remains == 0 {
|
if let availability = starGift.availability, availability.remains == 0 {
|
||||||
buttonIsEnabled = false
|
buttonIsEnabled = false
|
||||||
|
@ -14,6 +14,13 @@ import AnimatedStickerNode
|
|||||||
import TelegramAnimatedStickerNode
|
import TelegramAnimatedStickerNode
|
||||||
|
|
||||||
final class GiftCompositionComponent: Component {
|
final class GiftCompositionComponent: Component {
|
||||||
|
public class ExternalState {
|
||||||
|
public fileprivate(set) var previewPatternColor: UIColor?
|
||||||
|
public init() {
|
||||||
|
self.previewPatternColor = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
enum Subject: Equatable {
|
enum Subject: Equatable {
|
||||||
case generic(TelegramMediaFile)
|
case generic(TelegramMediaFile)
|
||||||
case unique(StarGift.UniqueGift)
|
case unique(StarGift.UniqueGift)
|
||||||
@ -23,15 +30,21 @@ final class GiftCompositionComponent: Component {
|
|||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
let subject: Subject
|
let subject: Subject
|
||||||
|
let externalState: ExternalState
|
||||||
|
let requestUpdate: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
subject: Subject
|
subject: Subject,
|
||||||
|
externalState: ExternalState,
|
||||||
|
requestUpdate: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.subject = subject
|
self.subject = subject
|
||||||
|
self.externalState = externalState
|
||||||
|
self.requestUpdate = requestUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
static func ==(lhs: GiftCompositionComponent, rhs: GiftCompositionComponent) -> Bool {
|
static func ==(lhs: GiftCompositionComponent, rhs: GiftCompositionComponent) -> Bool {
|
||||||
@ -194,12 +207,18 @@ final class GiftCompositionComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
component.externalState.previewPatternColor = secondBackgroundColor
|
||||||
|
|
||||||
var animateTransition = false
|
var animateTransition = false
|
||||||
if self.animatePreviewTransition {
|
if self.animatePreviewTransition {
|
||||||
animateTransition = true
|
animateTransition = true
|
||||||
self.animatePreviewTransition = false
|
self.animatePreviewTransition = false
|
||||||
} else if let previousComponent, case .preview = previousComponent.subject, case .unique = component.subject {
|
} else if let previousComponent, case .preview = previousComponent.subject, case .unique = component.subject {
|
||||||
animateTransition = true
|
animateTransition = true
|
||||||
|
} else if let previousComponent, case .generic = previousComponent.subject, case .preview = component.subject {
|
||||||
|
animateTransition = true
|
||||||
|
} else if let previousComponent, case .preview = previousComponent.subject, case .generic = component.subject {
|
||||||
|
animateTransition = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if let backgroundColor {
|
if let backgroundColor {
|
||||||
@ -235,7 +254,7 @@ final class GiftCompositionComponent: Component {
|
|||||||
backgroundTransition.setFrame(view: backgroundView, frame: CGRect(origin: .zero, size: availableSize))
|
backgroundTransition.setFrame(view: backgroundView, frame: CGRect(origin: .zero, size: availableSize))
|
||||||
}
|
}
|
||||||
} else if let backgroundView = self.background.view, backgroundView.superview != nil {
|
} else if let backgroundView = self.background.view, backgroundView.superview != nil {
|
||||||
backgroundView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, completion: { _ in
|
backgroundView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
||||||
backgroundView.removeFromSuperview()
|
backgroundView.removeFromSuperview()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -264,7 +283,6 @@ final class GiftCompositionComponent: Component {
|
|||||||
|
|
||||||
if let startFromIndex {
|
if let startFromIndex {
|
||||||
animationNode.play(firstFrame: false, fromIndex: startFromIndex)
|
animationNode.play(firstFrame: false, fromIndex: startFromIndex)
|
||||||
//animationNode.seekTo(.frameIndex(startFromIndex))
|
|
||||||
} else {
|
} else {
|
||||||
animationNode.playLoop()
|
animationNode.playLoop()
|
||||||
}
|
}
|
||||||
@ -276,31 +294,6 @@ final class GiftCompositionComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if self.animationLayer == nil, let animationFile {
|
|
||||||
// let emoji = ChatTextInputTextCustomEmojiAttribute(
|
|
||||||
// interactivelySelectedFromPackId: nil,
|
|
||||||
// fileId: animationFile.fileId.id,
|
|
||||||
// file: animationFile
|
|
||||||
// )
|
|
||||||
//
|
|
||||||
// let animationLayer = InlineStickerItemLayer(
|
|
||||||
// context: .account(component.context),
|
|
||||||
// userLocation: .other,
|
|
||||||
// attemptSynchronousLoad: false,
|
|
||||||
// emoji: emoji,
|
|
||||||
// file: animationFile,
|
|
||||||
// cache: component.context.animationCache,
|
|
||||||
// renderer: component.context.animationRenderer,
|
|
||||||
// unique: true,
|
|
||||||
// placeholderColor: component.theme.list.mediaPlaceholderColor,
|
|
||||||
// pointSize: CGSize(width: iconSize.width * 1.2, height: iconSize.height * 1.2),
|
|
||||||
// loopCount: 1
|
|
||||||
// )
|
|
||||||
// animationLayer.isVisibleForAnimations = true
|
|
||||||
// self.animationLayer = animationLayer
|
|
||||||
// self.layer.addSublayer(animationLayer)
|
|
||||||
// }
|
|
||||||
if let animationNode = self.animationNode {
|
if let animationNode = self.animationNode {
|
||||||
transition.setFrame(layer: animationNode.layer, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - iconSize.width) / 2.0), y: 25.0), size: iconSize))
|
transition.setFrame(layer: animationNode.layer, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - iconSize.width) / 2.0), y: 25.0), size: iconSize))
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
init(
|
init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
subject: GiftViewScreen.Subject,
|
subject: GiftViewScreen.Subject,
|
||||||
cancel: @escaping (Bool) -> Void,
|
cancel: @escaping (Bool) -> Void,
|
||||||
openPeer: @escaping (EnginePeer) -> Void,
|
openPeer: @escaping (EnginePeer) -> Void,
|
||||||
updateSavedToProfile: @escaping (Bool) -> Void,
|
updateSavedToProfile: @escaping (Bool) -> Void,
|
||||||
convertToStars: @escaping () -> Void,
|
convertToStars: @escaping () -> Void,
|
||||||
@ -108,11 +108,13 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
var inProgress = false
|
var inProgress = false
|
||||||
|
|
||||||
var inUpgradePreview = false
|
var inUpgradePreview = false
|
||||||
|
var upgradeForm: BotPaymentForm?
|
||||||
|
var upgradeDisposable: Disposable?
|
||||||
|
|
||||||
var sampleGiftAttributes: [StarGift.UniqueGift.Attribute]?
|
var sampleGiftAttributes: [StarGift.UniqueGift.Attribute]?
|
||||||
var sampleDisposable: Disposable?
|
let sampleDisposable = DisposableSet()
|
||||||
|
|
||||||
var keepOriginalInfo = false
|
var keepOriginalInfo = false
|
||||||
var upgradeDisposable: Disposable?
|
|
||||||
|
|
||||||
private var optionsDisposable: Disposable?
|
private var optionsDisposable: Disposable?
|
||||||
private(set) var options: [StarsTopUpOption] = [] {
|
private(set) var options: [StarsTopUpOption] = [] {
|
||||||
@ -151,15 +153,40 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if case let .generic(gift) = arguments.gift, let _ = arguments.upgradeStars {
|
} else if case let .generic(gift) = arguments.gift {
|
||||||
self.sampleDisposable = (context.engine.payments.starGiftUpgradePreview(giftId: gift.id)
|
if arguments.canUpgrade || arguments.upgradeStars != nil {
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] attributes in
|
self.sampleDisposable.add((context.engine.payments.starGiftUpgradePreview(giftId: gift.id)
|
||||||
guard let self else {
|
|> deliverOnMainQueue).start(next: { [weak self] attributes in
|
||||||
return
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.sampleGiftAttributes = attributes
|
||||||
|
|
||||||
|
for attribute in attributes {
|
||||||
|
switch attribute {
|
||||||
|
case let .model(_, file, _):
|
||||||
|
self.sampleDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start())
|
||||||
|
case let .pattern(_, file, _):
|
||||||
|
self.sampleDisposable.add(freeMediaFileResourceInteractiveFetched(account: self.context.account, userLocation: .other, fileReference: .standalone(media: file), resource: file.resource).start())
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.updated()
|
||||||
|
}))
|
||||||
|
|
||||||
|
if arguments.upgradeStars == nil, let messageId = arguments.messageId {
|
||||||
|
self.upgradeDisposable = (context.engine.payments.fetchBotPaymentForm(source: .starGiftUpgrade(keepOriginalInfo: false, messageId: messageId), themeParams: nil)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] paymentForm in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.upgradeForm = paymentForm
|
||||||
|
self.updated()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
self.sampleGiftAttributes = attributes
|
}
|
||||||
self.updated()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
self.disposable = combineLatest(queue: Queue.mainQueue(),
|
self.disposable = combineLatest(queue: Queue.mainQueue(),
|
||||||
context.engine.data.get(EngineDataMap(
|
context.engine.data.get(EngineDataMap(
|
||||||
@ -209,7 +236,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.disposable?.dispose()
|
self.disposable?.dispose()
|
||||||
self.sampleDisposable?.dispose()
|
self.sampleDisposable.dispose()
|
||||||
self.upgradeDisposable?.dispose()
|
self.upgradeDisposable?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,20 +244,22 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
guard let _ = self.subject.arguments?.upgradeStars else {
|
guard let _ = self.subject.arguments?.upgradeStars else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.context.starsContext?.load(force: false)
|
||||||
|
|
||||||
self.inUpgradePreview = true
|
self.inUpgradePreview = true
|
||||||
self.updated(transition: .spring(duration: 0.4))
|
self.updated(transition: .spring(duration: 0.4))
|
||||||
}
|
}
|
||||||
|
|
||||||
func commitUpgrade() {
|
func commitUpgrade() {
|
||||||
guard let arguments = self.subject.arguments, let messageId = arguments.messageId, let starsContext = self.context.starsContext, let starsState = starsContext.currentState, let upgradeStars = arguments.upgradeStars else {
|
guard let arguments = self.subject.arguments, let messageId = arguments.messageId, let starsContext = self.context.starsContext, let starsState = starsContext.currentState else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let peerId = arguments.peerId
|
let peerId = arguments.peerId
|
||||||
let proceed: (Bool) -> Void = { prepaid in
|
let proceed: (Int64?) -> Void = { formId in
|
||||||
self.inProgress = true
|
self.inProgress = true
|
||||||
self.updated()
|
self.updated()
|
||||||
|
|
||||||
let _ = (self.context.engine.payments.upgradeStarGift(prepaid: prepaid, messageId: messageId, keepOriginalInfo: self.keepOriginalInfo)
|
let _ = (self.context.engine.payments.upgradeStarGift(formId: formId, messageId: messageId, keepOriginalInfo: self.keepOriginalInfo)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] result in
|
|> deliverOnMainQueue).start(next: { [weak self] result in
|
||||||
guard let self, let controller = self.getController() as? GiftViewScreen else {
|
guard let self, let controller = self.getController() as? GiftViewScreen else {
|
||||||
return
|
return
|
||||||
@ -245,8 +274,10 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if upgradeStars > 0 {
|
if let upgradeStars = arguments.upgradeStars, upgradeStars > 0 {
|
||||||
if starsState.balance < StarsAmount(value: upgradeStars, nanos: 0) {
|
proceed(nil)
|
||||||
|
} else if let upgradeForm = self.upgradeForm, let price = upgradeForm.invoice.prices.first?.amount {
|
||||||
|
if starsState.balance < StarsAmount(value: price, nanos: 0) {
|
||||||
let _ = (self.optionsPromise.get()
|
let _ = (self.optionsPromise.get()
|
||||||
|> filter { $0 != nil }
|
|> filter { $0 != nil }
|
||||||
|> take(1)
|
|> take(1)
|
||||||
@ -258,21 +289,19 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
context: self.context,
|
context: self.context,
|
||||||
starsContext: starsContext,
|
starsContext: starsContext,
|
||||||
options: options ?? [],
|
options: options ?? [],
|
||||||
purpose: .upgradeStarGift(requiredStars: upgradeStars),
|
purpose: .upgradeStarGift(requiredStars: price),
|
||||||
completion: { [weak starsContext] stars in
|
completion: { [weak starsContext] stars in
|
||||||
starsContext?.add(balance: StarsAmount(value: stars, nanos: 0))
|
starsContext?.add(balance: StarsAmount(value: stars, nanos: 0))
|
||||||
Queue.mainQueue().after(2.0) {
|
Queue.mainQueue().after(2.0) {
|
||||||
proceed(false)
|
proceed(upgradeForm.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
controller.push(purchaseController)
|
controller.push(purchaseController)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
proceed(false)
|
proceed(upgradeForm.id)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
proceed(true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,6 +327,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let spaceRegex = try? NSRegularExpression(pattern: "\\[(.*?)\\]", options: [])
|
let spaceRegex = try? NSRegularExpression(pattern: "\\[(.*?)\\]", options: [])
|
||||||
|
|
||||||
|
let giftCompositionExternalState = GiftCompositionComponent.ExternalState()
|
||||||
|
|
||||||
return { context in
|
return { context in
|
||||||
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
|
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
|
||||||
|
|
||||||
@ -326,6 +357,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
var date: Int32?
|
var date: Int32?
|
||||||
var soldOut = false
|
var soldOut = false
|
||||||
var nameHidden = false
|
var nameHidden = false
|
||||||
|
var upgraded = false
|
||||||
|
var canUpgrade = false
|
||||||
var upgradeStars: Int64?
|
var upgradeStars: Int64?
|
||||||
var uniqueGift: StarGift.UniqueGift?
|
var uniqueGift: StarGift.UniqueGift?
|
||||||
if case let .soldOutGift(gift) = subject {
|
if case let .soldOutGift(gift) = subject {
|
||||||
@ -351,6 +384,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
converted = arguments.converted
|
converted = arguments.converted
|
||||||
giftId = gift.id
|
giftId = gift.id
|
||||||
date = arguments.date
|
date = arguments.date
|
||||||
|
upgraded = arguments.upgraded
|
||||||
|
canUpgrade = arguments.canUpgrade
|
||||||
upgradeStars = arguments.upgradeStars
|
upgradeStars = arguments.upgradeStars
|
||||||
case let .unique(gift):
|
case let .unique(gift):
|
||||||
stars = 0
|
stars = 0
|
||||||
@ -387,11 +422,27 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
state.cachedOverlayCloseImage = closeOverlayImage
|
state.cachedOverlayCloseImage = closeOverlayImage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var showUpgradePreview = false
|
||||||
|
if state.inUpgradePreview, let _ = state.sampleGiftAttributes {
|
||||||
|
showUpgradePreview = true
|
||||||
|
} else if case .upgradePreview = component.subject {
|
||||||
|
showUpgradePreview = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let cancel = component.cancel
|
||||||
let closeButton = closeButton.update(
|
let closeButton = closeButton.update(
|
||||||
component: Button(
|
component: Button(
|
||||||
content: AnyComponent(Image(image: state.inUpgradePreview || uniqueGift != nil ? closeOverlayImage : closeImage)),
|
content: AnyComponent(Image(image: showUpgradePreview || uniqueGift != nil ? closeOverlayImage : closeImage)),
|
||||||
action: { [weak component] in
|
action: { [weak state] in
|
||||||
component?.cancel(true)
|
guard let state else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if state.inUpgradePreview {
|
||||||
|
state.inUpgradePreview = false
|
||||||
|
state.updated(transition: .spring(duration: 0.4))
|
||||||
|
} else {
|
||||||
|
cancel(true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: 30.0, height: 30.0),
|
availableSize: CGSize(width: 30.0, height: 30.0),
|
||||||
@ -405,9 +456,12 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
if let uniqueGift {
|
if let uniqueGift {
|
||||||
animationHeight = 240.0
|
animationHeight = 240.0
|
||||||
animationSubject = .unique(uniqueGift)
|
animationSubject = .unique(uniqueGift)
|
||||||
} else if state.inUpgradePreview, let sampleGiftAttributes = state.sampleGiftAttributes {
|
} else if state.inUpgradePreview, let attributes = state.sampleGiftAttributes {
|
||||||
animationHeight = 258.0
|
animationHeight = 258.0
|
||||||
animationSubject = .preview(sampleGiftAttributes)
|
animationSubject = .preview(attributes)
|
||||||
|
} else if case let .upgradePreview(attributes, _) = component.subject {
|
||||||
|
animationHeight = 258.0
|
||||||
|
animationSubject = .preview(attributes)
|
||||||
} else if let animationFile {
|
} else if let animationFile {
|
||||||
animationHeight = 210.0
|
animationHeight = 210.0
|
||||||
animationSubject = .generic(animationFile)
|
animationSubject = .generic(animationFile)
|
||||||
@ -420,7 +474,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component: GiftCompositionComponent(
|
component: GiftCompositionComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
subject: animationSubject
|
subject: animationSubject,
|
||||||
|
externalState: giftCompositionExternalState,
|
||||||
|
requestUpdate: { [weak state] in
|
||||||
|
state?.updated()
|
||||||
|
}
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: context.availableSize.width, height: animationHeight),
|
availableSize: CGSize(width: context.availableSize.width, height: animationHeight),
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
@ -431,12 +489,30 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
originY += animationHeight
|
originY += animationHeight
|
||||||
|
|
||||||
|
if showUpgradePreview {
|
||||||
|
let title: String
|
||||||
|
let description: String
|
||||||
|
let uniqueText: String
|
||||||
|
let transferableText: String
|
||||||
|
let tradableText: String
|
||||||
|
if case let .upgradePreview(_, name) = component.subject {
|
||||||
|
title = environment.strings.Gift_Upgrade_IncludeTitle
|
||||||
|
description = environment.strings.Gift_Upgrade_IncludeDescription(name).string
|
||||||
|
uniqueText = strings.Gift_Upgrade_Unique_IncludeDescription
|
||||||
|
transferableText = strings.Gift_Upgrade_Transferable_IncludeDescription
|
||||||
|
tradableText = strings.Gift_Upgrade_Tradable_IncludeDescription
|
||||||
|
} else {
|
||||||
|
title = environment.strings.Gift_Upgrade_Title
|
||||||
|
description = environment.strings.Gift_Upgrade_Description
|
||||||
|
uniqueText = strings.Gift_Upgrade_Unique_Description
|
||||||
|
transferableText = strings.Gift_Upgrade_Transferable_Description
|
||||||
|
tradableText = strings.Gift_Upgrade_Tradable_Description
|
||||||
|
}
|
||||||
|
|
||||||
if state.inUpgradePreview, let _ = state.sampleGiftAttributes {
|
|
||||||
let upgradeTitle = upgradeTitle.update(
|
let upgradeTitle = upgradeTitle.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: environment.strings.Gift_Upgrade_Title,
|
string: title,
|
||||||
font: Font.bold(20.0),
|
font: Font.bold(20.0),
|
||||||
textColor: .white,
|
textColor: .white,
|
||||||
paragraphAlignment: .center
|
paragraphAlignment: .center
|
||||||
@ -447,18 +523,18 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude),
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude),
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
)
|
)
|
||||||
context.add(upgradeTitle
|
let descriptionColor: UIColor
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: 191.0))
|
if let previewPatternColor = giftCompositionExternalState.previewPatternColor {
|
||||||
.appear(.default(alpha: true))
|
descriptionColor = previewPatternColor.withMultiplied(hue: 1.0, saturation: 1.02, brightness: 1.25).mixedWith(UIColor.white, alpha: 0.3)
|
||||||
.disappear(.default(alpha: true))
|
} else {
|
||||||
)
|
descriptionColor = UIColor.white.withAlphaComponent(0.6)
|
||||||
|
}
|
||||||
let upgradeDescription = upgradeDescription.update(
|
let upgradeDescription = upgradeDescription.update(
|
||||||
component: BalancedTextComponent(
|
component: BalancedTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: environment.strings.Gift_Upgrade_Description,
|
string: description,
|
||||||
font: Font.regular(13.0),
|
font: Font.regular(13.0),
|
||||||
textColor: UIColor.white.withAlphaComponent(0.6),
|
textColor: descriptionColor,
|
||||||
paragraphAlignment: .center
|
paragraphAlignment: .center
|
||||||
)),
|
)),
|
||||||
horizontalAlignment: .center,
|
horizontalAlignment: .center,
|
||||||
@ -468,8 +544,18 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 50.0, height: CGFloat.greatestFiniteMagnitude),
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 50.0, height: CGFloat.greatestFiniteMagnitude),
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let spacing: CGFloat = 6.0
|
||||||
|
let totalHeight: CGFloat = upgradeTitle.size.height + spacing + upgradeDescription.size.height
|
||||||
|
|
||||||
|
context.add(upgradeTitle
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: floor(212.0 - totalHeight / 2.0 + upgradeTitle.size.height / 2.0)))
|
||||||
|
.appear(.default(alpha: true))
|
||||||
|
.disappear(.default(alpha: true))
|
||||||
|
)
|
||||||
|
|
||||||
context.add(upgradeDescription
|
context.add(upgradeDescription
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: 208.0 + upgradeDescription.size.height / 2.0))
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: floor(212.0 + totalHeight / 2.0 - upgradeDescription.size.height / 2.0)))
|
||||||
.appear(.default(alpha: true))
|
.appear(.default(alpha: true))
|
||||||
.disappear(.default(alpha: true))
|
.disappear(.default(alpha: true))
|
||||||
)
|
)
|
||||||
@ -486,7 +572,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: strings.Gift_Upgrade_Unique_Title,
|
title: strings.Gift_Upgrade_Unique_Title,
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: strings.Gift_Upgrade_Unique_Description,
|
text: uniqueText,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/Collectible/Unique",
|
iconName: "Premium/Collectible/Unique",
|
||||||
@ -500,7 +586,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: strings.Gift_Upgrade_Transferable_Title,
|
title: strings.Gift_Upgrade_Transferable_Title,
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: strings.Gift_Upgrade_Transferable_Description,
|
text: transferableText,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/Collectible/Transferable",
|
iconName: "Premium/Collectible/Transferable",
|
||||||
@ -514,7 +600,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
component: AnyComponent(ParagraphComponent(
|
component: AnyComponent(ParagraphComponent(
|
||||||
title: strings.Gift_Upgrade_Tradable_Title,
|
title: strings.Gift_Upgrade_Tradable_Title,
|
||||||
titleColor: textColor,
|
titleColor: textColor,
|
||||||
text: strings.Gift_Upgrade_Tradable_Description,
|
text: tradableText,
|
||||||
textColor: secondaryTextColor,
|
textColor: secondaryTextColor,
|
||||||
accentColor: linkColor,
|
accentColor: linkColor,
|
||||||
iconName: "Premium/Collectible/Tradable",
|
iconName: "Premium/Collectible/Tradable",
|
||||||
@ -538,55 +624,59 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
originY += upgradePerks.size.height
|
originY += upgradePerks.size.height
|
||||||
originY += 16.0
|
originY += 16.0
|
||||||
|
|
||||||
let checkTheme = CheckComponent.Theme(
|
if case .upgradePreview = component.subject {
|
||||||
backgroundColor: theme.list.itemCheckColors.fillColor,
|
|
||||||
strokeColor: theme.list.itemCheckColors.foregroundColor,
|
|
||||||
borderColor: theme.list.itemCheckColors.strokeColor,
|
|
||||||
overlayBorder: false,
|
|
||||||
hasInset: false,
|
|
||||||
hasShadow: false
|
|
||||||
)
|
|
||||||
let keepInfoText: String
|
|
||||||
if let nameHidden = subject.arguments?.nameHidden, nameHidden {
|
|
||||||
keepInfoText = strings.Gift_Upgrade_AddMyName
|
|
||||||
} else {
|
} else {
|
||||||
keepInfoText = text != nil ? strings.Gift_Upgrade_AddNameAndComment : strings.Gift_Upgrade_AddName
|
let checkTheme = CheckComponent.Theme(
|
||||||
|
backgroundColor: theme.list.itemCheckColors.fillColor,
|
||||||
|
strokeColor: theme.list.itemCheckColors.foregroundColor,
|
||||||
|
borderColor: theme.list.itemCheckColors.strokeColor,
|
||||||
|
overlayBorder: false,
|
||||||
|
hasInset: false,
|
||||||
|
hasShadow: false
|
||||||
|
)
|
||||||
|
let keepInfoText: String
|
||||||
|
if let nameHidden = subject.arguments?.nameHidden, nameHidden {
|
||||||
|
keepInfoText = strings.Gift_Upgrade_AddMyName
|
||||||
|
} else {
|
||||||
|
keepInfoText = text != nil ? strings.Gift_Upgrade_AddNameAndComment : strings.Gift_Upgrade_AddName
|
||||||
|
}
|
||||||
|
let upgradeKeepName = upgradeKeepName.update(
|
||||||
|
component: PlainButtonComponent(
|
||||||
|
content: AnyComponent(HStack([
|
||||||
|
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(CheckComponent(
|
||||||
|
theme: checkTheme,
|
||||||
|
size: CGSize(width: 18.0, height: 18.0),
|
||||||
|
selected: state.keepOriginalInfo
|
||||||
|
))),
|
||||||
|
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
|
||||||
|
text: .plain(NSAttributedString(string: keepInfoText, font: Font.regular(13.0), textColor: theme.list.itemSecondaryTextColor))
|
||||||
|
)))
|
||||||
|
],
|
||||||
|
spacing: 10.0
|
||||||
|
)),
|
||||||
|
effectAlignment: .center,
|
||||||
|
action: { [weak state] in
|
||||||
|
guard let state else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
state.keepOriginalInfo = !state.keepOriginalInfo
|
||||||
|
state.updated(transition: .easeInOut(duration: 0.2))
|
||||||
|
},
|
||||||
|
animateAlpha: false,
|
||||||
|
animateScale: false
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 1000.0),
|
||||||
|
transition: context.transition
|
||||||
|
)
|
||||||
|
context.add(upgradeKeepName
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + upgradeKeepName.size.height / 2.0))
|
||||||
|
.appear(.default(alpha: true))
|
||||||
|
.disappear(.default(alpha: true))
|
||||||
|
)
|
||||||
|
originY += upgradeKeepName.size.height
|
||||||
|
originY += 18.0
|
||||||
}
|
}
|
||||||
let upgradeKeepName = upgradeKeepName.update(
|
|
||||||
component: PlainButtonComponent(
|
|
||||||
content: AnyComponent(HStack([
|
|
||||||
AnyComponentWithIdentity(id: AnyHashable(0), component: AnyComponent(CheckComponent(
|
|
||||||
theme: checkTheme,
|
|
||||||
size: CGSize(width: 18.0, height: 18.0),
|
|
||||||
selected: state.keepOriginalInfo
|
|
||||||
))),
|
|
||||||
AnyComponentWithIdentity(id: AnyHashable(1), component: AnyComponent(MultilineTextComponent(
|
|
||||||
text: .plain(NSAttributedString(string: keepInfoText, font: Font.regular(13.0), textColor: theme.list.itemSecondaryTextColor))
|
|
||||||
)))
|
|
||||||
],
|
|
||||||
spacing: 10.0
|
|
||||||
)),
|
|
||||||
effectAlignment: .center,
|
|
||||||
action: { [weak state] in
|
|
||||||
guard let state else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
state.keepOriginalInfo = !state.keepOriginalInfo
|
|
||||||
state.updated(transition: .easeInOut(duration: 0.2))
|
|
||||||
},
|
|
||||||
animateAlpha: false,
|
|
||||||
animateScale: false
|
|
||||||
),
|
|
||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 1000.0),
|
|
||||||
transition: context.transition
|
|
||||||
)
|
|
||||||
context.add(upgradeKeepName
|
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + upgradeKeepName.size.height / 2.0))
|
|
||||||
.appear(.default(alpha: true))
|
|
||||||
.disappear(.default(alpha: true))
|
|
||||||
)
|
|
||||||
originY += upgradeKeepName.size.height
|
|
||||||
originY += 18.0
|
|
||||||
} else {
|
} else {
|
||||||
var descriptionText: String
|
var descriptionText: String
|
||||||
if let uniqueGift {
|
if let uniqueGift {
|
||||||
@ -595,12 +685,18 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
} else if soldOut {
|
} else if soldOut {
|
||||||
descriptionText = strings.Gift_View_UnavailableDescription
|
descriptionText = strings.Gift_View_UnavailableDescription
|
||||||
} else if incoming {
|
} else if incoming {
|
||||||
if let convertStars {
|
if let convertStars, !upgraded {
|
||||||
if !converted {
|
if !converted {
|
||||||
descriptionText = strings.Gift_View_KeepUpgradeOrConvertDescription(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string
|
if canUpgrade || upgradeStars != nil {
|
||||||
|
descriptionText = strings.Gift_View_KeepUpgradeOrConvertDescription(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string
|
||||||
|
} else {
|
||||||
|
descriptionText = strings.Gift_View_KeepOrConvertDescription(strings.Gift_View_KeepOrConvertDescription_Stars(Int32(convertStars))).string
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
descriptionText = strings.Gift_View_ConvertedDescription(strings.Gift_View_ConvertedDescription_Stars(Int32(convertStars))).string
|
descriptionText = strings.Gift_View_ConvertedDescription(strings.Gift_View_ConvertedDescription_Stars(Int32(convertStars))).string
|
||||||
}
|
}
|
||||||
|
} else if (canUpgrade || upgradeStars != nil) && !upgraded {
|
||||||
|
descriptionText = strings.Gift_View_KeepOrUpgradeDescription
|
||||||
} else {
|
} else {
|
||||||
descriptionText = strings.Gift_View_BotDescription
|
descriptionText = strings.Gift_View_BotDescription
|
||||||
}
|
}
|
||||||
@ -660,17 +756,13 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
|
|
||||||
let textFont: UIFont
|
let textFont: UIFont
|
||||||
let textColor: UIColor
|
let textColor: UIColor
|
||||||
if let uniqueGift {
|
if let _ = uniqueGift {
|
||||||
textFont = Font.regular(13.0)
|
textFont = Font.regular(13.0)
|
||||||
|
if let previewPatternColor = giftCompositionExternalState.previewPatternColor {
|
||||||
var giftTextColor: UIColor?
|
textColor = previewPatternColor.withMultiplied(hue: 1.0, saturation: 1.02, brightness: 1.25).mixedWith(UIColor.white, alpha: 0.3)
|
||||||
for attribute in uniqueGift.attributes {
|
} else {
|
||||||
if case let .backdrop(_, _, _, _, textColor, _) = attribute {
|
textColor = UIColor.white.withAlphaComponent(0.6)
|
||||||
giftTextColor = UIColor(rgb: UInt32(bitPattern: textColor))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
textColor = giftTextColor ?? UIColor.white.withAlphaComponent(0.6)
|
|
||||||
} else {
|
} else {
|
||||||
textFont = soldOut ? Font.medium(15.0) : Font.regular(15.0)
|
textFont = soldOut ? Font.medium(15.0) : Font.regular(15.0)
|
||||||
textColor = soldOut ? theme.list.itemDestructiveColor : theme.list.itemPrimaryTextColor
|
textColor = soldOut ? theme.list.itemDestructiveColor : theme.list.itemPrimaryTextColor
|
||||||
@ -1043,7 +1135,11 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
let valueString = "⭐️\(presentationStringsFormattedNumber(abs(Int32(stars)), dateTimeFormat.groupingSeparator))"
|
var finalStars = stars
|
||||||
|
if let upgradeStars, upgradeStars > 0 {
|
||||||
|
finalStars += upgradeStars
|
||||||
|
}
|
||||||
|
let valueString = "⭐️\(presentationStringsFormattedNumber(abs(Int32(finalStars)), dateTimeFormat.groupingSeparator))"
|
||||||
let valueAttributedString = NSMutableAttributedString(string: valueString, font: tableFont, textColor: tableTextColor)
|
let valueAttributedString = NSMutableAttributedString(string: valueString, font: tableFont, textColor: tableTextColor)
|
||||||
let range = (valueAttributedString.string as NSString).range(of: "⭐️")
|
let range = (valueAttributedString.string as NSString).range(of: "⭐️")
|
||||||
if range.location != NSNotFound {
|
if range.location != NSNotFound {
|
||||||
@ -1115,7 +1211,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
if !soldOut && upgradeStars != nil {
|
if !soldOut && canUpgrade {
|
||||||
var items: [AnyComponentWithIdentity<Empty>] = []
|
var items: [AnyComponentWithIdentity<Empty>] = []
|
||||||
items.append(
|
items.append(
|
||||||
AnyComponentWithIdentity(
|
AnyComponentWithIdentity(
|
||||||
@ -1190,7 +1286,14 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
if state.cachedSmallChevronImage == nil || state.cachedSmallChevronImage?.1 !== environment.theme {
|
if state.cachedSmallChevronImage == nil || state.cachedSmallChevronImage?.1 !== environment.theme {
|
||||||
state.cachedSmallChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: linkColor)!, theme)
|
state.cachedSmallChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: linkColor)!, theme)
|
||||||
}
|
}
|
||||||
let descriptionText = savedToProfile ? strings.Gift_View_DisplayedInfoHide : strings.Gift_View_HiddenInfo
|
let descriptionText: String
|
||||||
|
if savedToProfile {
|
||||||
|
descriptionText = strings.Gift_View_DisplayedInfoHide
|
||||||
|
} else if let upgradeStars, upgradeStars > 0 && !upgraded {
|
||||||
|
descriptionText = strings.Gift_View_HiddenInfoShow
|
||||||
|
} else {
|
||||||
|
descriptionText = strings.Gift_View_HiddenInfo
|
||||||
|
}
|
||||||
|
|
||||||
let textFont = Font.regular(13.0)
|
let textFont = Font.regular(13.0)
|
||||||
let textColor = theme.list.itemSecondaryTextColor
|
let textColor = theme.list.itemSecondaryTextColor
|
||||||
@ -1219,7 +1322,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
tapAction: { _, _ in
|
tapAction: { _, _ in
|
||||||
component.updateSavedToProfile(false)
|
component.updateSavedToProfile(!savedToProfile)
|
||||||
Queue.mainQueue().after(1.0, {
|
Queue.mainQueue().after(1.0, {
|
||||||
component.cancel(false)
|
component.cancel(false)
|
||||||
})
|
})
|
||||||
@ -1239,11 +1342,15 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let buttonChild: _UpdatedChildComponent
|
let buttonChild: _UpdatedChildComponent
|
||||||
if state.inUpgradePreview, let upgradeStars = subject.arguments?.upgradeStars {
|
if state.inUpgradePreview {
|
||||||
if state.cachedStarImage == nil || state.cachedStarImage?.1 !== theme {
|
if state.cachedStarImage == nil || state.cachedStarImage?.1 !== theme {
|
||||||
state.cachedStarImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: theme.list.itemCheckColors.foregroundColor)!, theme)
|
state.cachedStarImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: theme.list.itemCheckColors.foregroundColor)!, theme)
|
||||||
}
|
}
|
||||||
let buttonTitle = upgradeStars > 0 ? "\(strings.Gift_Upgrade_Upgrade) # \(upgradeStars)" : strings.Gift_Upgrade_Confirm
|
var upgradeString = strings.Gift_Upgrade_Upgrade
|
||||||
|
if let upgradeForm = state.upgradeForm, let price = upgradeForm.invoice.prices.first?.amount {
|
||||||
|
upgradeString += " # \(price)"
|
||||||
|
}
|
||||||
|
let buttonTitle = subject.arguments?.upgradeStars != nil ? strings.Gift_Upgrade_Confirm : upgradeString
|
||||||
let buttonAttributedString = NSMutableAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
let buttonAttributedString = NSMutableAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center)
|
||||||
if let range = buttonAttributedString.string.range(of: "#"), let starImage = state.cachedStarImage?.0 {
|
if let range = buttonAttributedString.string.range(of: "#"), let starImage = state.cachedStarImage?.0 {
|
||||||
buttonAttributedString.addAttribute(.attachment, value: starImage, range: NSRange(range, in: buttonAttributedString.string))
|
buttonAttributedString.addAttribute(.attachment, value: starImage, range: NSRange(range, in: buttonAttributedString.string))
|
||||||
@ -1259,7 +1366,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
cornerRadius: 10.0
|
cornerRadius: 10.0
|
||||||
),
|
),
|
||||||
content: AnyComponentWithIdentity(
|
content: AnyComponentWithIdentity(
|
||||||
id: AnyHashable(0),
|
id: AnyHashable("upgrade"),
|
||||||
component: AnyComponent(MultilineTextComponent(text: .plain(buttonAttributedString)))
|
component: AnyComponent(MultilineTextComponent(text: .plain(buttonAttributedString)))
|
||||||
),
|
),
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
@ -1270,7 +1377,8 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
|
||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
} else if incoming && !converted && !savedToProfile {
|
} else if incoming && !converted && !upgraded, let upgradeStars, upgradeStars > 0 {
|
||||||
|
let buttonTitle = strings.Gift_View_UpgradeForFree
|
||||||
buttonChild = button.update(
|
buttonChild = button.update(
|
||||||
component: ButtonComponent(
|
component: ButtonComponent(
|
||||||
background: ButtonComponent.Background(
|
background: ButtonComponent.Background(
|
||||||
@ -1280,8 +1388,36 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
cornerRadius: 10.0
|
cornerRadius: 10.0
|
||||||
),
|
),
|
||||||
content: AnyComponentWithIdentity(
|
content: AnyComponentWithIdentity(
|
||||||
id: AnyHashable(0),
|
id: AnyHashable("freeUpgrade"),
|
||||||
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: savedToProfile ? strings.Gift_View_Hide : strings.Gift_View_Display, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
component: AnyComponent(HStack([
|
||||||
|
AnyComponentWithIdentity(id: 0, component: AnyComponent(
|
||||||
|
MultilineTextComponent(text: .plain(NSAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))
|
||||||
|
))),
|
||||||
|
AnyComponentWithIdentity(id: 1, component: AnyComponent(BundleIconComponent(name: "Premium/GiftUpgrade", tintColor: theme.list.itemCheckColors.foregroundColor)))
|
||||||
|
], spacing: 6.0))
|
||||||
|
),
|
||||||
|
isEnabled: true,
|
||||||
|
displaysProgress: state.inProgress,
|
||||||
|
action: { [weak state] in
|
||||||
|
state?.requestUpgradePreview()
|
||||||
|
}
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0, height: 50.0),
|
||||||
|
transition: context.transition
|
||||||
|
)
|
||||||
|
} else if incoming && !converted && !savedToProfile {
|
||||||
|
let buttonTitle = savedToProfile ? strings.Gift_View_Hide : strings.Gift_View_Display
|
||||||
|
buttonChild = button.update(
|
||||||
|
component: ButtonComponent(
|
||||||
|
background: ButtonComponent.Background(
|
||||||
|
color: theme.list.itemCheckColors.fillColor,
|
||||||
|
foreground: theme.list.itemCheckColors.foregroundColor,
|
||||||
|
pressedColor: theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.9),
|
||||||
|
cornerRadius: 10.0
|
||||||
|
),
|
||||||
|
content: AnyComponentWithIdentity(
|
||||||
|
id: AnyHashable("button"),
|
||||||
|
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: buttonTitle, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
||||||
),
|
),
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
displaysProgress: state.inProgress,
|
displaysProgress: state.inProgress,
|
||||||
@ -1301,7 +1437,7 @@ private final class GiftViewSheetContent: CombinedComponent {
|
|||||||
cornerRadius: 10.0
|
cornerRadius: 10.0
|
||||||
),
|
),
|
||||||
content: AnyComponentWithIdentity(
|
content: AnyComponentWithIdentity(
|
||||||
id: AnyHashable(0),
|
id: AnyHashable("ok"),
|
||||||
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Common_OK, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Common_OK, font: Font.semibold(17.0), textColor: theme.list.itemCheckColors.foregroundColor, paragraphAlignment: .center))))
|
||||||
),
|
),
|
||||||
isEnabled: true,
|
isEnabled: true,
|
||||||
@ -1486,24 +1622,31 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
case message(EngineMessage)
|
case message(EngineMessage)
|
||||||
case profileGift(EnginePeer.Id, ProfileGiftsContext.State.StarGift)
|
case profileGift(EnginePeer.Id, ProfileGiftsContext.State.StarGift)
|
||||||
case soldOutGift(StarGift.Gift)
|
case soldOutGift(StarGift.Gift)
|
||||||
|
case upgradePreview([StarGift.UniqueGift.Attribute], String)
|
||||||
|
|
||||||
var arguments: (peerId: EnginePeer.Id, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, incoming: Bool, gift: StarGift, date: Int32, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, canUpgrade: Bool, upgradeStars: Int64?, transferStars: Int64?, canExportDate: Int32?)? {
|
var arguments: (peerId: EnginePeer.Id, fromPeerId: EnginePeer.Id?, fromPeerName: String?, messageId: EngineMessage.Id?, incoming: Bool, gift: StarGift, date: Int32, convertStars: Int64?, text: String?, entities: [MessageTextEntity]?, nameHidden: Bool, savedToProfile: Bool, converted: Bool, upgraded: Bool, canUpgrade: Bool, upgradeStars: Int64?, transferStars: Int64?, canExportDate: Int32?)? {
|
||||||
switch self {
|
switch self {
|
||||||
case let .message(message):
|
case let .message(message):
|
||||||
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
|
if let action = message.media.first(where: { $0 is TelegramMediaAction }) as? TelegramMediaAction {
|
||||||
switch action.action {
|
switch action.action {
|
||||||
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, _, upgradeStars):
|
case let .starGift(gift, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, _):
|
||||||
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, converted, false, upgradeStars, nil, nil)
|
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, message.timestamp, convertStars, text, entities, nameHidden, savedToProfile, converted, upgraded, canUpgrade, upgradeStars, nil, nil)
|
||||||
case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars):
|
case let .starGiftUnique(gift, _, _, savedToProfile, canExportDate, transferStars, _):
|
||||||
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, message.timestamp, nil, nil, nil, false, savedToProfile, false, false, nil, transferStars, canExportDate)
|
return (message.id.peerId, message.author?.id, message.author?.compactDisplayTitle, message.id, message.flags.contains(.Incoming), gift, message.timestamp, nil, nil, nil, false, savedToProfile, false, true, false, nil, transferStars, canExportDate)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case let .profileGift(peerId, gift):
|
case let .profileGift(peerId, gift):
|
||||||
return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, gift.messageId, false, gift.gift, gift.date, gift.convertStars, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, false, gift.canUpgrade, gift.upgradeStars, gift.transferStars, gift.canExportDate)
|
var upgraded = false
|
||||||
|
if case .unique = gift.gift {
|
||||||
|
upgraded = true
|
||||||
|
}
|
||||||
|
return (peerId, gift.fromPeer?.id, gift.fromPeer?.compactDisplayTitle, gift.messageId, false, gift.gift, gift.date, gift.convertStars, gift.text, gift.entities, gift.nameHidden, gift.savedToProfile, false, upgraded, gift.canUpgrade, gift.upgradeStars, gift.transferStars, gift.canExportDate)
|
||||||
case .soldOutGift:
|
case .soldOutGift:
|
||||||
return nil
|
return nil
|
||||||
|
case .upgradePreview:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1772,6 +1915,8 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.dismissAllTooltips()
|
||||||
|
|
||||||
guard let sourceView = self.node.hostView.findTaggedView(tag: tag), let absoluteLocation = sourceView.superview?.convert(sourceView.center, to: self.view) else {
|
guard let sourceView = self.node.hostView.findTaggedView(tag: tag), let absoluteLocation = sourceView.superview?.convert(sourceView.center, to: self.view) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1818,13 +1963,16 @@ public class GiftViewScreen: ViewControllerComponentContainer {
|
|||||||
fileprivate func dismissAllTooltips() {
|
fileprivate func dismissAllTooltips() {
|
||||||
self.window?.forEachController({ controller in
|
self.window?.forEachController({ controller in
|
||||||
if let controller = controller as? TooltipScreen {
|
if let controller = controller as? TooltipScreen {
|
||||||
controller.dismiss()
|
controller.dismiss(inPlace: false)
|
||||||
}
|
}
|
||||||
if let controller = controller as? UndoOverlayController {
|
if let controller = controller as? UndoOverlayController {
|
||||||
controller.dismiss()
|
controller.dismiss()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
self.forEachController({ controller in
|
self.forEachController({ controller in
|
||||||
|
if let controller = controller as? TooltipScreen {
|
||||||
|
controller.dismiss(inPlace: false)
|
||||||
|
}
|
||||||
if let controller = controller as? UndoOverlayController {
|
if let controller = controller as? UndoOverlayController {
|
||||||
controller.dismiss()
|
controller.dismiss()
|
||||||
}
|
}
|
||||||
|
@ -222,29 +222,24 @@ public final class PeerInfoCoverComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func animateTransition() {
|
public func animateTransition() {
|
||||||
if let snapshotLayer = self.backgroundView.layer.snapshotContentTree() {
|
if let gradientSnapshotLayer = self.backgroundGradientLayer.snapshotContentTree() {
|
||||||
self.layer.insertSublayer(snapshotLayer, above: self.backgroundGradientLayer)
|
gradientSnapshotLayer.frame = self.backgroundGradientLayer.frame
|
||||||
if let gradientSnapshotLayer = self.backgroundGradientLayer.snapshotContentTree() {
|
self.layer.insertSublayer(gradientSnapshotLayer, above: self.backgroundGradientLayer)
|
||||||
self.layer.insertSublayer(gradientSnapshotLayer, above: snapshotLayer)
|
gradientSnapshotLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
||||||
snapshotLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
gradientSnapshotLayer.removeFromSuperlayer()
|
||||||
snapshotLayer.removeFromSuperlayer()
|
})
|
||||||
})
|
|
||||||
gradientSnapshotLayer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
|
||||||
gradientSnapshotLayer.removeFromSuperlayer()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for layer in self.avatarPatternContentLayers {
|
for layer in self.avatarPatternContentLayers {
|
||||||
if let snapshot = layer.snapshotContentTree() {
|
if let _ = layer.contents, let snapshot = layer.snapshotContentTree() {
|
||||||
layer.superlayer?.addSublayer(snapshot)
|
layer.superlayer?.addSublayer(snapshot)
|
||||||
snapshot.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
snapshot.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
||||||
snapshot.removeFromSuperlayer()
|
snapshot.removeFromSuperlayer()
|
||||||
})
|
})
|
||||||
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
|
||||||
}
|
}
|
||||||
|
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||||
}
|
}
|
||||||
let values: [NSNumber] = [1.0, 1.08, 1.0]
|
let values: [NSNumber] = [1.0, 1.08, 1.0]
|
||||||
self.avatarBackgroundPatternContentsLayer.animateKeyframes(values: values, duration: 0.25, keyPath: "transform.scale")
|
self.avatarBackgroundPatternContentsLayer.animateKeyframes(values: values, duration: 0.25, keyPath: "sublayerTransform.scale")
|
||||||
}
|
}
|
||||||
|
|
||||||
private func loadPatternFromFile() {
|
private func loadPatternFromFile() {
|
||||||
@ -298,7 +293,10 @@ public final class PeerInfoCoverComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func update(component: PeerInfoCoverComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
func update(component: PeerInfoCoverComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
if self.component?.subject?.fileId != component.subject?.fileId {
|
let previousComponent = self.component
|
||||||
|
self.component = component
|
||||||
|
|
||||||
|
if previousComponent?.subject?.fileId != component.subject?.fileId {
|
||||||
if let fileId = component.subject?.fileId, fileId != 0 {
|
if let fileId = component.subject?.fileId, fileId != 0 {
|
||||||
if self.patternContentsTarget == nil {
|
if self.patternContentsTarget == nil {
|
||||||
self.patternContentsTarget = PatternContentsTarget(imageUpdated: { [weak self] hadContents in
|
self.patternContentsTarget = PatternContentsTarget(imageUpdated: { [weak self] hadContents in
|
||||||
@ -338,7 +336,6 @@ public final class PeerInfoCoverComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.component = component
|
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
let backgroundColor: UIColor
|
let backgroundColor: UIColor
|
||||||
|
@ -1210,9 +1210,15 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, ASGestureRecognizerDelegat
|
|||||||
case .gifts:
|
case .gifts:
|
||||||
title = presentationData.strings.PeerInfo_PaneGifts
|
title = presentationData.strings.PeerInfo_PaneGifts
|
||||||
icons = data?.profileGiftsContext?.currentState?.gifts.prefix(3).compactMap { gift in
|
icons = data?.profileGiftsContext?.currentState?.gifts.prefix(3).compactMap { gift in
|
||||||
if case let .generic(gift) = gift.gift {
|
switch gift.gift {
|
||||||
|
case let .generic(gift):
|
||||||
return gift.file
|
return gift.file
|
||||||
} else {
|
case let .unique(gift):
|
||||||
|
for attribute in gift.attributes {
|
||||||
|
if case let .model(_, file, _) = attribute {
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
} ?? []
|
} ?? []
|
||||||
|
12
submodules/TelegramUI/Images.xcassets/Premium/GiftUnpack.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Premium/GiftUnpack.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "unpack_14.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
submodules/TelegramUI/Images.xcassets/Premium/GiftUnpack.imageset/unpack_14.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Premium/GiftUnpack.imageset/unpack_14.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Premium/GiftUpgrade.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Premium/GiftUpgrade.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "upgrade_30.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
submodules/TelegramUI/Images.xcassets/Premium/GiftUpgrade.imageset/upgrade_30.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Premium/GiftUpgrade.imageset/upgrade_30.pdf
vendored
Normal file
Binary file not shown.
@ -2289,18 +2289,13 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
var currentBirthdays: [EnginePeer.Id: TelegramBirthday]?
|
var currentBirthdays: [EnginePeer.Id: TelegramBirthday]?
|
||||||
|
|
||||||
if case let .starGiftTransfer(birthdays, _, _, _, _) = source {
|
if case let .starGiftTransfer(birthdays, _, _, _, _) = source {
|
||||||
if let birthdays, !birthdays.isEmpty {
|
mode = .starsGifting(birthdays: birthdays, hasActions: false, showSelf: false)
|
||||||
mode = .starsGifting(birthdays: birthdays, hasActions: false, showSelf: true)
|
|
||||||
currentBirthdays = birthdays
|
|
||||||
} else {
|
|
||||||
mode = .starsGifting(birthdays: nil, hasActions: false, showSelf: true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if case let .chatList(birthdays) = source, let birthdays, !birthdays.isEmpty {
|
|
||||||
mode = .starsGifting(birthdays: birthdays, hasActions: true, showSelf: false)
|
|
||||||
currentBirthdays = birthdays
|
currentBirthdays = birthdays
|
||||||
} else if case let .settings(birthdays) = source, let birthdays, !birthdays.isEmpty {
|
} else if case let .chatList(birthdays) = source {
|
||||||
mode = .starsGifting(birthdays: birthdays, hasActions: true, showSelf: false)
|
mode = .starsGifting(birthdays: birthdays, hasActions: true, showSelf: true)
|
||||||
|
currentBirthdays = birthdays
|
||||||
|
} else if case let .settings(birthdays) = source {
|
||||||
|
mode = .starsGifting(birthdays: birthdays, hasActions: true, showSelf: true)
|
||||||
currentBirthdays = birthdays
|
currentBirthdays = birthdays
|
||||||
} else {
|
} else {
|
||||||
mode = .starsGifting(birthdays: nil, hasActions: true, showSelf: false)
|
mode = .starsGifting(birthdays: nil, hasActions: true, showSelf: false)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user