mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
e050bb2119
commit
9bb28dcc26
@ -10525,6 +10525,7 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Message.AdSponsoredLabel" = "Sponsored";
|
"Message.AdSponsoredLabel" = "Sponsored";
|
||||||
"Message.AdRecommendedLabel" = "Recommended";
|
"Message.AdRecommendedLabel" = "Recommended";
|
||||||
|
"Message.AdWhatIsThis" = "what's this?";
|
||||||
|
|
||||||
"Stats.StoryTitle" = "Story Statistics";
|
"Stats.StoryTitle" = "Story Statistics";
|
||||||
|
|
||||||
@ -11682,7 +11683,7 @@ Sorry for the inconvenience.";
|
|||||||
"Monetization.AdRevenueTitle" = "AD REVENUE";
|
"Monetization.AdRevenueTitle" = "AD REVENUE";
|
||||||
"Monetization.OverviewTitle" = "PROCEEDS OVERVIEW";
|
"Monetization.OverviewTitle" = "PROCEEDS OVERVIEW";
|
||||||
"Monetization.BalanceTitle" = "AVAILABLE BALANCE";
|
"Monetization.BalanceTitle" = "AVAILABLE BALANCE";
|
||||||
"Monetization.BalanceInfo" = "You will be able to collect rewards using Fragment, a third-party platform used by the advertizer to pay for the ad. [Learn More >]()";
|
"Monetization.BalanceInfo" = "You will be able to collect rewards using Fragment, a third-party platform used by advertisers to pay for ads. [Learn More >]()";
|
||||||
"Monetization.BalanceInfo_URL" = "https://telegram.org";
|
"Monetization.BalanceInfo_URL" = "https://telegram.org";
|
||||||
"Monetization.BalanceWithdraw" = "Withdraw via Fragment";
|
"Monetization.BalanceWithdraw" = "Withdraw via Fragment";
|
||||||
"Monetization.TransactionsTitle" = "TRANSACTION HISTORY";
|
"Monetization.TransactionsTitle" = "TRANSACTION HISTORY";
|
||||||
|
@ -410,7 +410,7 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
|||||||
if let additionalDetailLabel = item.additionalDetailLabel {
|
if let additionalDetailLabel = item.additionalDetailLabel {
|
||||||
var detailRightInset: CGFloat = 20.0 + params.rightInset + additionalTextRightInset
|
var detailRightInset: CGFloat = 20.0 + params.rightInset + additionalTextRightInset
|
||||||
if labelLayout.size.width != 0 {
|
if labelLayout.size.width != 0 {
|
||||||
detailRightInset += labelLayout.size.width + 12.0
|
detailRightInset += labelLayout.size.width + 7.0
|
||||||
}
|
}
|
||||||
let additionalDetailColor: UIColor
|
let additionalDetailColor: UIColor
|
||||||
switch item.additionalDetailLabelColor {
|
switch item.additionalDetailLabelColor {
|
||||||
|
@ -179,7 +179,7 @@ private final class SheetPageContent: CombinedComponent {
|
|||||||
maximumNumberOfLines: 1
|
maximumNumberOfLines: 1
|
||||||
))),
|
))),
|
||||||
], alignment: .left, spacing: 2.0)),
|
], alignment: .left, spacing: 2.0)),
|
||||||
accessory: nil,
|
accessory: .arrow,
|
||||||
action: { _ in
|
action: { _ in
|
||||||
component.action(item)
|
component.action(item)
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,9 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
private var contentFile: ChatMessageInteractiveFileNode?
|
private var contentFile: ChatMessageInteractiveFileNode?
|
||||||
private var actionButton: ChatMessageAttachedContentButtonNode?
|
private var actionButton: ChatMessageAttachedContentButtonNode?
|
||||||
private var actionButtonSeparator: SimpleLayer?
|
private var actionButtonSeparator: SimpleLayer?
|
||||||
|
|
||||||
|
private var titleBadgeLabel: TextNode?
|
||||||
|
private var titleBadgeButton: HighlightTrackingButtonNode?
|
||||||
public var statusNode: ChatMessageDateAndStatusNode?
|
public var statusNode: ChatMessageDateAndStatusNode?
|
||||||
|
|
||||||
private var closeButton: ComponentView<Empty>?
|
private var closeButton: ComponentView<Empty>?
|
||||||
@ -104,12 +107,14 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
private var message: Message?
|
private var message: Message?
|
||||||
private var media: Media?
|
private var media: Media?
|
||||||
private var theme: ChatPresentationThemeData?
|
private var theme: ChatPresentationThemeData?
|
||||||
|
private var mainColor: UIColor?
|
||||||
|
|
||||||
private var isHighlighted: Bool = false
|
private var isHighlighted: Bool = false
|
||||||
private var highlightTimer: Foundation.Timer?
|
private var highlightTimer: Foundation.Timer?
|
||||||
|
|
||||||
public var openMedia: ((InteractiveMediaNodeActivateContent) -> Void)?
|
public var openMedia: ((InteractiveMediaNodeActivateContent) -> Void)?
|
||||||
public var activateAction: (() -> Void)?
|
public var activateAction: (() -> Void)?
|
||||||
|
public var activateBadgeAction: (() -> Void)?
|
||||||
public var requestUpdateLayout: (() -> Void)?
|
public var requestUpdateLayout: (() -> Void)?
|
||||||
|
|
||||||
private var currentProgressDisposable: Disposable?
|
private var currentProgressDisposable: Disposable?
|
||||||
@ -153,6 +158,10 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
self.activateAction?()
|
self.activateAction?()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func badgePressed() {
|
||||||
|
self.activateBadgeAction?()
|
||||||
|
}
|
||||||
|
|
||||||
public typealias AsyncLayout = (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ chatLocation: ChatLocation, _ title: String?, _ titleBadge: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: (Media, ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ constrainedSize: CGSize, _ animationCache: AnimationCache, _ animationRenderer: MultiAnimationRenderer) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void)))
|
public typealias AsyncLayout = (_ presentationData: ChatPresentationData, _ automaticDownloadSettings: MediaAutoDownloadSettings, _ associatedData: ChatMessageItemAssociatedData, _ attributes: ChatMessageEntryAttributes, _ context: AccountContext, _ controllerInteraction: ChatControllerInteraction, _ message: Message, _ messageRead: Bool, _ chatLocation: ChatLocation, _ title: String?, _ titleBadge: String?, _ subtitle: NSAttributedString?, _ text: String?, _ entities: [MessageTextEntity]?, _ media: (Media, ChatMessageAttachedContentNodeMediaFlags)?, _ mediaBadge: String?, _ actionIcon: ChatMessageAttachedContentActionIcon?, _ actionTitle: String?, _ displayLine: Bool, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ constrainedSize: CGSize, _ animationCache: AnimationCache, _ animationRenderer: MultiAnimationRenderer) -> (CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void)))
|
||||||
|
|
||||||
public func makeProgress() -> Promise<Bool> {
|
public func makeProgress() -> Promise<Bool> {
|
||||||
@ -173,6 +182,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
let makeTitleLayout = TextNodeWithEntities.asyncLayout(self.title)
|
let makeTitleLayout = TextNodeWithEntities.asyncLayout(self.title)
|
||||||
let makeSubtitleLayout = TextNodeWithEntities.asyncLayout(self.subtitle)
|
let makeSubtitleLayout = TextNodeWithEntities.asyncLayout(self.subtitle)
|
||||||
let makeTextLayout = TextNodeWithEntities.asyncLayout(self.text)
|
let makeTextLayout = TextNodeWithEntities.asyncLayout(self.text)
|
||||||
|
let makeTitleBadgeLayout = TextNode.asyncLayout(self.titleBadgeLabel)
|
||||||
let makeContentMedia = ChatMessageInteractiveMediaNode.asyncLayout(self.contentMedia)
|
let makeContentMedia = ChatMessageInteractiveMediaNode.asyncLayout(self.contentMedia)
|
||||||
let makeContentFile = ChatMessageInteractiveFileNode.asyncLayout(self.contentFile)
|
let makeContentFile = ChatMessageInteractiveFileNode.asyncLayout(self.contentFile)
|
||||||
let makeActionButtonLayout = ChatMessageAttachedContentButtonNode.asyncLayout(self.actionButton)
|
let makeActionButtonLayout = ChatMessageAttachedContentButtonNode.asyncLayout(self.actionButton)
|
||||||
@ -194,6 +204,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
let textBoldItalicFont = Font.semiboldItalic(fontSize)
|
let textBoldItalicFont = Font.semiboldItalic(fontSize)
|
||||||
let textFixedFont = Font.regular(fontSize)
|
let textFixedFont = Font.regular(fontSize)
|
||||||
let textBlockQuoteFont = Font.regular(fontSize)
|
let textBlockQuoteFont = Font.regular(fontSize)
|
||||||
|
let badgeFont = Font.regular(floor(presentationData.fontSize.baseDisplaySize * 11.0 / 17.0))
|
||||||
|
|
||||||
var incoming = message.effectivelyIncoming(context.account.peerId)
|
var incoming = message.effectivelyIncoming(context.account.peerId)
|
||||||
if let subject = associatedData.subject, case let .messageOptions(_, _, info) = subject, case .forward = info {
|
if let subject = associatedData.subject, case let .messageOptions(_, _, info) = subject, case .forward = info {
|
||||||
@ -489,6 +500,7 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
var titleLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
var titleLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
||||||
var subtitleLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
var subtitleLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
||||||
var textLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
var textLayoutAndApply: (TextNodeLayout, (TextNodeWithEntities.Arguments?) -> TextNodeWithEntities)?
|
||||||
|
var titleBadgeLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||||
|
|
||||||
var remainingCutoutHeight: CGFloat = 0.0
|
var remainingCutoutHeight: CGFloat = 0.0
|
||||||
var cutoutWidth: CGFloat = 0.0
|
var cutoutWidth: CGFloat = 0.0
|
||||||
@ -509,6 +521,11 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
let titleLayoutAndApplyValue = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: maxContentsWidth, height: 10000.0), alignment: .natural, lineSpacing: textLineSpacing, cutout: cutout, insets: UIEdgeInsets()))
|
let titleLayoutAndApplyValue = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: maxContentsWidth, height: 10000.0), alignment: .natural, lineSpacing: textLineSpacing, cutout: cutout, insets: UIEdgeInsets()))
|
||||||
titleLayoutAndApply = titleLayoutAndApplyValue
|
titleLayoutAndApply = titleLayoutAndApplyValue
|
||||||
|
|
||||||
|
if let titleBadge {
|
||||||
|
let titleBadgeString = NSAttributedString(string: titleBadge, font: badgeFont, textColor: mainColor)
|
||||||
|
titleBadgeLayoutAndApply = makeTitleBadgeLayout(TextNodeLayoutArguments(attributedString: titleBadgeString, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: maxContentsWidth, height: 10000.0)))
|
||||||
|
}
|
||||||
|
|
||||||
remainingCutoutHeight -= titleLayoutAndApplyValue.0.size.height
|
remainingCutoutHeight -= titleLayoutAndApplyValue.0.size.height
|
||||||
}
|
}
|
||||||
case .subtitle:
|
case .subtitle:
|
||||||
@ -548,8 +565,13 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let titleBadgePadding: CGFloat = 5.0
|
||||||
|
let titleBadgeSpacing: CGFloat = 5.0
|
||||||
if let (titleLayout, _) = titleLayoutAndApply {
|
if let (titleLayout, _) = titleLayoutAndApply {
|
||||||
actualWidth = max(actualWidth, titleLayout.size.width)
|
actualWidth = max(actualWidth, titleLayout.size.width)
|
||||||
|
if let (titleBadgeLayout, _) = titleBadgeLayoutAndApply {
|
||||||
|
actualWidth = max(actualWidth, titleLayout.size.width + titleBadgeLayout.size.width + (titleBadgePadding + titleBadgeSpacing) * 2.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let (subtitleLayout, _) = subtitleLayoutAndApply {
|
if let (subtitleLayout, _) = subtitleLayoutAndApply {
|
||||||
actualWidth = max(actualWidth, subtitleLayout.size.width)
|
actualWidth = max(actualWidth, subtitleLayout.size.width)
|
||||||
@ -921,10 +943,13 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let themeUpdated = self.theme !== presentationData.theme || self.mainColor != mainColor
|
||||||
|
|
||||||
self.context = context
|
self.context = context
|
||||||
self.message = message
|
self.message = message
|
||||||
self.media = mediaAndFlags?.0
|
self.media = mediaAndFlags?.0
|
||||||
self.theme = presentationData.theme
|
self.theme = presentationData.theme
|
||||||
|
self.mainColor = mainColor
|
||||||
|
|
||||||
animation.animator.updateFrame(layer: self.transformContainer.layer, frame: CGRect(origin: CGPoint(), size: actualSize), completion: nil)
|
animation.animator.updateFrame(layer: self.transformContainer.layer, frame: CGRect(origin: CGPoint(), size: actualSize), completion: nil)
|
||||||
|
|
||||||
@ -1061,11 +1086,71 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
title.textNode.bounds = CGRect(origin: CGPoint(), size: titleFrame.size)
|
title.textNode.bounds = CGRect(origin: CGPoint(), size: titleFrame.size)
|
||||||
animation.animator.updatePosition(layer: title.textNode.layer, position: titleFrame.origin, completion: nil)
|
animation.animator.updatePosition(layer: title.textNode.layer, position: titleFrame.origin, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let (titleBadgeLayout, titleBadgeApply) = titleBadgeLayoutAndApply {
|
||||||
|
let titleBadgeLabel = titleBadgeApply()
|
||||||
|
let titleBadgeFrame = CGRect(origin: CGPoint(x: titleFrame.maxX + titleBadgeSpacing + titleBadgePadding, y: floorToScreenPixels(titleFrame.midY - titleBadgeLayout.size.height / 2.0)), size: titleBadgeLayout.size)
|
||||||
|
let badgeBackgroundFrame = titleBadgeFrame.insetBy(dx: -titleBadgePadding, dy: -1.0 + UIScreenPixel)
|
||||||
|
|
||||||
|
let button: HighlightTrackingButtonNode
|
||||||
|
if let current = self.titleBadgeButton {
|
||||||
|
button = current
|
||||||
|
button.bounds = CGRect(origin: .zero, size: badgeBackgroundFrame.size)
|
||||||
|
animation.animator.updatePosition(layer: button.layer, position: badgeBackgroundFrame.center, completion: nil)
|
||||||
|
} else {
|
||||||
|
button = HighlightTrackingButtonNode()
|
||||||
|
button.addTarget(self, action: #selector(self.badgePressed), forControlEvents: .touchUpInside)
|
||||||
|
button.frame = badgeBackgroundFrame
|
||||||
|
button.highligthedChanged = { [weak self, weak button] highlighted in
|
||||||
|
if let self, let button {
|
||||||
|
if highlighted {
|
||||||
|
button.layer.removeAnimation(forKey: "opacity")
|
||||||
|
button.alpha = 0.4
|
||||||
|
self.titleBadgeLabel?.layer.removeAnimation(forKey: "opacity")
|
||||||
|
self.titleBadgeLabel?.alpha = 0.4
|
||||||
|
} else {
|
||||||
|
button.alpha = 1.0
|
||||||
|
button.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||||
|
self.titleBadgeLabel?.alpha = 1.0
|
||||||
|
self.titleBadgeLabel?.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.titleBadgeButton = button
|
||||||
|
self.transformContainer.addSubnode(button)
|
||||||
|
}
|
||||||
|
|
||||||
|
if themeUpdated || button.backgroundImage(for: .normal) == nil {
|
||||||
|
button.setBackgroundImage(generateFilledCircleImage(diameter: badgeBackgroundFrame.height, color: mainColor.withMultipliedAlpha(0.1))?.stretchableImage(withLeftCapWidth: Int(badgeBackgroundFrame.height / 2), topCapHeight: Int(badgeBackgroundFrame.height / 2)), for: .normal)
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.titleBadgeLabel !== titleBadgeLabel {
|
||||||
|
self.titleBadgeLabel?.removeFromSupernode()
|
||||||
|
self.titleBadgeLabel = titleBadgeLabel
|
||||||
|
titleBadgeLabel.layer.anchorPoint = CGPoint()
|
||||||
|
titleBadgeLabel.isUserInteractionEnabled = false
|
||||||
|
self.transformContainer.addSubnode(titleBadgeLabel)
|
||||||
|
|
||||||
|
titleBadgeLabel.frame = titleBadgeFrame
|
||||||
|
titleBadgeLabel.displaysAsynchronously = !presentationData.isPreview
|
||||||
|
} else {
|
||||||
|
titleBadgeLabel.bounds = CGRect(origin: CGPoint(), size: titleBadgeFrame.size)
|
||||||
|
animation.animator.updatePosition(layer: titleBadgeLabel.layer, position: titleBadgeFrame.origin, completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if let title = self.title {
|
if let title = self.title {
|
||||||
self.title = nil
|
self.title = nil
|
||||||
title.textNode.removeFromSupernode()
|
title.textNode.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
if let titleBadgeLabel = self.titleBadgeLabel {
|
||||||
|
self.titleBadgeLabel = nil
|
||||||
|
titleBadgeLabel.removeFromSupernode()
|
||||||
|
}
|
||||||
|
if let titleBadgeButton = self.titleBadgeButton {
|
||||||
|
self.titleBadgeButton = nil
|
||||||
|
titleBadgeButton.removeFromSupernode()
|
||||||
|
}
|
||||||
if let closeButton = self.closeButton {
|
if let closeButton = self.closeButton {
|
||||||
self.closeButton = nil
|
self.closeButton = nil
|
||||||
closeButton.view?.removeFromSuperview()
|
closeButton.view?.removeFromSuperview()
|
||||||
@ -1449,6 +1534,10 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
return ChatMessageBubbleContentTapAction(content: .ignore)
|
return ChatMessageBubbleContentTapAction(content: .ignore)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let titleBadgeButton = self.titleBadgeButton, titleBadgeButton.frame.contains(point) {
|
||||||
|
return ChatMessageBubbleContentTapAction(content: .ignore)
|
||||||
|
}
|
||||||
|
|
||||||
if let backgroundView = self.backgroundView, backgroundView.frame.contains(point) {
|
if let backgroundView = self.backgroundView, backgroundView.frame.contains(point) {
|
||||||
if let message = self.message, message.adAttribute != nil {
|
if let message = self.message, message.adAttribute != nil {
|
||||||
return ChatMessageBubbleContentTapAction(content: .none)
|
return ChatMessageBubbleContentTapAction(content: .none)
|
||||||
|
@ -25,6 +25,7 @@ public class ChatMessageShareButton: ASDisplayNode {
|
|||||||
|
|
||||||
private var theme: PresentationTheme?
|
private var theme: PresentationTheme?
|
||||||
private var isReplies: Bool = false
|
private var isReplies: Bool = false
|
||||||
|
private var hasMore: Bool = false
|
||||||
|
|
||||||
private var textNode: ImmediateTextNode?
|
private var textNode: ImmediateTextNode?
|
||||||
|
|
||||||
@ -97,18 +98,26 @@ public class ChatMessageShareButton: ASDisplayNode {
|
|||||||
isReplies = false
|
isReplies = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.theme !== presentationData.theme.theme || self.isReplies != isReplies {
|
var hasMore = false
|
||||||
|
if let adAttribute = message.adAttribute, adAttribute.canReport {
|
||||||
|
hasMore = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.theme !== presentationData.theme.theme || self.isReplies != isReplies || self.hasMore != hasMore {
|
||||||
self.theme = presentationData.theme.theme
|
self.theme = presentationData.theme.theme
|
||||||
self.isReplies = isReplies
|
self.isReplies = isReplies
|
||||||
|
self.hasMore = hasMore
|
||||||
|
|
||||||
var updatedIconImage: UIImage?
|
var updatedIconImage: UIImage?
|
||||||
var updatedBottomIconImage: UIImage?
|
var updatedBottomIconImage: UIImage?
|
||||||
var updatedIconOffset = CGPoint()
|
var updatedIconOffset = CGPoint()
|
||||||
if message.adAttribute != nil {
|
if let _ = message.adAttribute {
|
||||||
updatedIconImage = PresentationResourcesChat.chatFreeCloseButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
updatedIconImage = PresentationResourcesChat.chatFreeCloseButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
||||||
updatedIconOffset = CGPoint(x: UIScreenPixel, y: UIScreenPixel)
|
updatedIconOffset = CGPoint(x: UIScreenPixel, y: UIScreenPixel)
|
||||||
|
|
||||||
updatedBottomIconImage = PresentationResourcesChat.chatFreeMoreButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
if hasMore {
|
||||||
|
updatedBottomIconImage = PresentationResourcesChat.chatFreeMoreButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
||||||
|
}
|
||||||
} else if case .pinnedMessages = subject {
|
} else if case .pinnedMessages = subject {
|
||||||
updatedIconImage = PresentationResourcesChat.chatFreeNavigateButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
updatedIconImage = PresentationResourcesChat.chatFreeNavigateButtonIcon(presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper)
|
||||||
updatedIconOffset = CGPoint(x: UIScreenPixel, y: 1.0)
|
updatedIconOffset = CGPoint(x: UIScreenPixel, y: 1.0)
|
||||||
@ -173,7 +182,7 @@ public class ChatMessageShareButton: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var size = CGSize(width: 30.0, height: 30.0)
|
var size = CGSize(width: 30.0, height: 30.0)
|
||||||
if message.adAttribute != nil {
|
if hasMore {
|
||||||
size.height += 30.0
|
size.height += 30.0
|
||||||
}
|
}
|
||||||
var offsetIcon = false
|
var offsetIcon = false
|
||||||
|
@ -132,6 +132,11 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.contentNode.activateBadgeAction = { [weak self] in
|
||||||
|
if let strongSelf = self, let item = strongSelf.item {
|
||||||
|
item.controllerInteraction.openAdsInfo()
|
||||||
|
}
|
||||||
|
}
|
||||||
self.contentNode.activateAction = { [weak self] in
|
self.contentNode.activateAction = { [weak self] in
|
||||||
if let strongSelf = self, let item = strongSelf.item {
|
if let strongSelf = self, let item = strongSelf.item {
|
||||||
if let _ = item.message.adAttribute {
|
if let _ = item.message.adAttribute {
|
||||||
@ -506,7 +511,9 @@ public final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
titleBadge = "what's this?"
|
if adAttribute.canReport {
|
||||||
|
titleBadge = item.presentationData.strings.Message_AdWhatIsThis
|
||||||
|
}
|
||||||
|
|
||||||
if let buttonText = adAttribute.buttonText {
|
if let buttonText = adAttribute.buttonText {
|
||||||
actionTitle = buttonText.uppercased()
|
actionTitle = buttonText.uppercased()
|
||||||
|
@ -568,6 +568,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
}, openRequestedPeerSelection: { _, _, _, _ in
|
}, openRequestedPeerSelection: { _, _, _, _ in
|
||||||
}, saveMediaToFiles: { _ in
|
}, saveMediaToFiles: { _ in
|
||||||
}, openNoAdsDemo: {
|
}, openNoAdsDemo: {
|
||||||
|
}, openAdsInfo: {
|
||||||
}, displayGiveawayParticipationStatus: { _ in
|
}, displayGiveawayParticipationStatus: { _ in
|
||||||
}, openPremiumStatusInfo: { _, _, _, _ in
|
}, openPremiumStatusInfo: { _, _, _, _ in
|
||||||
}, openRecommendedChannelContextMenu: { _, _, _ in
|
}, openRecommendedChannelContextMenu: { _, _, _ in
|
||||||
|
@ -228,6 +228,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
|
|||||||
public let openRequestedPeerSelection: (EngineMessage.Id, ReplyMarkupButtonRequestPeerType, Int32, Int32) -> Void
|
public let openRequestedPeerSelection: (EngineMessage.Id, ReplyMarkupButtonRequestPeerType, Int32, Int32) -> Void
|
||||||
public let saveMediaToFiles: (EngineMessage.Id) -> Void
|
public let saveMediaToFiles: (EngineMessage.Id) -> Void
|
||||||
public let openNoAdsDemo: () -> Void
|
public let openNoAdsDemo: () -> Void
|
||||||
|
public let openAdsInfo: () -> Void
|
||||||
public let displayGiveawayParticipationStatus: (EngineMessage.Id) -> Void
|
public let displayGiveawayParticipationStatus: (EngineMessage.Id) -> Void
|
||||||
public let openPremiumStatusInfo: (EnginePeer.Id, UIView, Int64?, PeerNameColor) -> Void
|
public let openPremiumStatusInfo: (EnginePeer.Id, UIView, Int64?, PeerNameColor) -> Void
|
||||||
public let openRecommendedChannelContextMenu: (EnginePeer, UIView, ContextGesture?) -> Void
|
public let openRecommendedChannelContextMenu: (EnginePeer, UIView, ContextGesture?) -> Void
|
||||||
@ -352,6 +353,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
|
|||||||
openRequestedPeerSelection: @escaping (EngineMessage.Id, ReplyMarkupButtonRequestPeerType, Int32, Int32) -> Void,
|
openRequestedPeerSelection: @escaping (EngineMessage.Id, ReplyMarkupButtonRequestPeerType, Int32, Int32) -> Void,
|
||||||
saveMediaToFiles: @escaping (EngineMessage.Id) -> Void,
|
saveMediaToFiles: @escaping (EngineMessage.Id) -> Void,
|
||||||
openNoAdsDemo: @escaping () -> Void,
|
openNoAdsDemo: @escaping () -> Void,
|
||||||
|
openAdsInfo: @escaping () -> Void,
|
||||||
displayGiveawayParticipationStatus: @escaping (EngineMessage.Id) -> Void,
|
displayGiveawayParticipationStatus: @escaping (EngineMessage.Id) -> Void,
|
||||||
openPremiumStatusInfo: @escaping (EnginePeer.Id, UIView, Int64?, PeerNameColor) -> Void,
|
openPremiumStatusInfo: @escaping (EnginePeer.Id, UIView, Int64?, PeerNameColor) -> Void,
|
||||||
openRecommendedChannelContextMenu: @escaping (EnginePeer, UIView, ContextGesture?) -> Void,
|
openRecommendedChannelContextMenu: @escaping (EnginePeer, UIView, ContextGesture?) -> Void,
|
||||||
@ -456,6 +458,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
|
|||||||
self.openRequestedPeerSelection = openRequestedPeerSelection
|
self.openRequestedPeerSelection = openRequestedPeerSelection
|
||||||
self.saveMediaToFiles = saveMediaToFiles
|
self.saveMediaToFiles = saveMediaToFiles
|
||||||
self.openNoAdsDemo = openNoAdsDemo
|
self.openNoAdsDemo = openNoAdsDemo
|
||||||
|
self.openAdsInfo = openAdsInfo
|
||||||
self.displayGiveawayParticipationStatus = displayGiveawayParticipationStatus
|
self.displayGiveawayParticipationStatus = displayGiveawayParticipationStatus
|
||||||
self.openPremiumStatusInfo = openPremiumStatusInfo
|
self.openPremiumStatusInfo = openPremiumStatusInfo
|
||||||
self.openRecommendedChannelContextMenu = openRecommendedChannelContextMenu
|
self.openRecommendedChannelContextMenu = openRecommendedChannelContextMenu
|
||||||
|
@ -3232,6 +3232,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
controller.statusBar.statusBarStyle = .Ignore
|
controller.statusBar.statusBarStyle = .Ignore
|
||||||
self.isUserInteractionEnabled = false
|
self.isUserInteractionEnabled = false
|
||||||
|
|
||||||
|
self.saveTooltip?.dismiss()
|
||||||
|
|
||||||
if self.entitiesView.hasSelection {
|
if self.entitiesView.hasSelection {
|
||||||
self.entitiesView.selectEntity(nil)
|
self.entitiesView.selectEntity(nil)
|
||||||
}
|
}
|
||||||
@ -3472,7 +3474,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
self.controller?.present(tooltipController, in: .current)
|
self.controller?.present(tooltipController, in: .current)
|
||||||
}
|
}
|
||||||
|
|
||||||
private weak var saveTooltip: SaveProgressScreen?
|
fileprivate weak var saveTooltip: SaveProgressScreen?
|
||||||
func presentSaveTooltip() {
|
func presentSaveTooltip() {
|
||||||
guard let controller = self.controller else {
|
guard let controller = self.controller else {
|
||||||
return
|
return
|
||||||
@ -3525,7 +3527,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
controller.cancelVideoExport()
|
controller.cancelVideoExport()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
controller.present(tooltipController, in: .current)
|
controller.present(tooltipController, in: .window(.root))
|
||||||
self.saveTooltip = tooltipController
|
self.saveTooltip = tooltipController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3554,7 +3556,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
controller.requestLayout(transition: .animated(duration: 0.25, curve: .easeInOut))
|
controller.requestLayout(transition: .animated(duration: 0.25, curve: .easeInOut))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
controller.present(tooltipController, in: .current)
|
controller.present(tooltipController, in: .window(.root))
|
||||||
self.saveTooltip = tooltipController
|
self.saveTooltip = tooltipController
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5768,10 +5770,17 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
}
|
}
|
||||||
|
|
||||||
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
let resource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||||
|
let thumbnailResource = LocalFileMediaResource(fileId: Int64.random(in: Int64.min ... Int64.max))
|
||||||
|
|
||||||
var isVideo = false
|
var isVideo = false
|
||||||
if mediaEditor.resultIsVideo {
|
if mediaEditor.resultIsVideo {
|
||||||
isVideo = true
|
isVideo = true
|
||||||
|
|
||||||
|
Queue.concurrentDefaultQueue().async {
|
||||||
|
if let data = try? WebP.convert(toWebP: image, quality: 97.0) {
|
||||||
|
self.context.account.postbox.mediaBox.storeResourceData(thumbnailResource.id, data: data)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Queue.concurrentDefaultQueue().async {
|
Queue.concurrentDefaultQueue().async {
|
||||||
if let data = try? WebP.convert(toWebP: image, quality: 97.0) {
|
if let data = try? WebP.convert(toWebP: image, quality: 97.0) {
|
||||||
@ -5782,7 +5791,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
|
|
||||||
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkColorPresentationTheme)
|
let presentationData = self.context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkColorPresentationTheme)
|
||||||
|
|
||||||
let file = stickerFile(resource: resource, size: Int64(0), dimensions: PixelDimensions(image.size), isVideo: isVideo)
|
let file = stickerFile(resource: resource, thumbnailResource: thumbnailResource, size: Int64(0), dimensions: PixelDimensions(image.size), isVideo: isVideo)
|
||||||
|
|
||||||
var menuItems: [ContextMenuItem] = []
|
var menuItems: [ContextMenuItem] = []
|
||||||
if case let .stickerEditor(mode) = self.mode {
|
if case let .stickerEditor(mode) = self.mode {
|
||||||
@ -6073,7 +6082,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
case let .progress(progress):
|
case let .progress(progress):
|
||||||
return .single(.progress(isVideo ? 0.5 + progress * 0.5 : progress))
|
return .single(.progress(isVideo ? 0.5 + progress * 0.5 : progress))
|
||||||
case let .complete(resource, _):
|
case let .complete(resource, _):
|
||||||
let file = stickerFile(resource: resource, size: file.size ?? 0, dimensions: dimensions, isVideo: isVideo)
|
let file = stickerFile(resource: resource, thumbnailResource: file.previewRepresentations.first?.resource, size: file.size ?? 0, dimensions: dimensions, isVideo: isVideo)
|
||||||
switch action {
|
switch action {
|
||||||
case .send:
|
case .send:
|
||||||
return .single(status)
|
return .single(status)
|
||||||
@ -6147,7 +6156,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||||||
let result: MediaEditorScreen.Result
|
let result: MediaEditorScreen.Result
|
||||||
switch action {
|
switch action {
|
||||||
case .upload, .send:
|
case .upload, .send:
|
||||||
let file = stickerFile(resource: resource, size: resource.size ?? 0, dimensions: dimensions, isVideo: isVideo)
|
let file = stickerFile(resource: resource, thumbnailResource: file.previewRepresentations.first?.resource, size: resource.size ?? 0, dimensions: dimensions, isVideo: isVideo)
|
||||||
result = MediaEditorScreen.Result(media: .sticker(file: file))
|
result = MediaEditorScreen.Result(media: .sticker(file: file))
|
||||||
default:
|
default:
|
||||||
result = MediaEditorScreen.Result()
|
result = MediaEditorScreen.Result()
|
||||||
@ -7045,11 +7054,16 @@ extension MediaScrubberComponent.Track {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func stickerFile(resource: TelegramMediaResource, size: Int64, dimensions: PixelDimensions, isVideo: Bool) -> TelegramMediaFile {
|
private func stickerFile(resource: TelegramMediaResource, thumbnailResource: TelegramMediaResource?, size: Int64, dimensions: PixelDimensions, isVideo: Bool) -> TelegramMediaFile {
|
||||||
var fileAttributes: [TelegramMediaFileAttribute] = []
|
var fileAttributes: [TelegramMediaFileAttribute] = []
|
||||||
fileAttributes.append(.FileName(fileName: isVideo ? "sticker.webm" : "sticker.webp"))
|
fileAttributes.append(.FileName(fileName: isVideo ? "sticker.webm" : "sticker.webp"))
|
||||||
fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil))
|
fileAttributes.append(.Sticker(displayText: "", packReference: nil, maskData: nil))
|
||||||
fileAttributes.append(.ImageSize(size: dimensions))
|
fileAttributes.append(.ImageSize(size: dimensions))
|
||||||
|
|
||||||
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: [], videoThumbnails: [], immediateThumbnailData: nil, mimeType: isVideo ? "video/webm" : "image/webp", size: size, attributes: fileAttributes)
|
var previewRepresentations: [TelegramMediaImageRepresentation] = []
|
||||||
|
if let thumbnailResource {
|
||||||
|
previewRepresentations.append(TelegramMediaImageRepresentation(dimensions: dimensions, resource: thumbnailResource, progressiveSizes: [], immediateThumbnailData: nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
return TelegramMediaFile(fileId: MediaId(namespace: Namespaces.Media.LocalFile, id: Int64.random(in: Int64.min ... Int64.max)), partialReference: nil, resource: resource, previewRepresentations: previewRepresentations, videoThumbnails: [], immediateThumbnailData: nil, mimeType: isVideo ? "video/webm" : "image/webp", size: size, attributes: fileAttributes)
|
||||||
}
|
}
|
||||||
|
@ -486,7 +486,8 @@ public final class SaveProgressScreen: ViewController {
|
|||||||
self.view.addSubview(componentView)
|
self.view.addSubview(componentView)
|
||||||
}
|
}
|
||||||
let componentFrame = CGRect(origin: .zero, size: componentSize)
|
let componentFrame = CGRect(origin: .zero, size: componentSize)
|
||||||
transition.setFrame(view: componentView, frame: CGRect(origin: componentFrame.origin, size: CGSize(width: componentFrame.width, height: componentFrame.height)))
|
componentView.center = componentFrame.center
|
||||||
|
componentView.bounds = CGRect(origin: .zero, size: componentFrame.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if isFirstTime {
|
if isFirstTime {
|
||||||
|
@ -32,7 +32,6 @@ final class PeerInfoBirthdayOverlay: ASDisplayNode {
|
|||||||
self.setupAnimations(size: size, birthday: birthday, sourceRect: sourceRect)
|
self.setupAnimations(size: size, birthday: birthday, sourceRect: sourceRect)
|
||||||
|
|
||||||
Queue.mainQueue().after(0.1) {
|
Queue.mainQueue().after(0.1) {
|
||||||
HapticFeedback().success()
|
|
||||||
self.view.addSubview(ConfettiView(frame: CGRect(origin: .zero, size: size)))
|
self.view.addSubview(ConfettiView(frame: CGRect(origin: .zero, size: size)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2696,7 +2696,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
if let self {
|
if let self {
|
||||||
if value {
|
if value {
|
||||||
if let data = self.data?.cachedData as? CachedUserData {
|
if let data = self.data?.cachedData as? CachedUserData {
|
||||||
if data.birthday == nil && self.state.updatingBirthDate == nil {
|
if data.birthday == nil && (self.state.updatingBirthDate == nil || self.state.updatingBirthDate == .some(nil)) {
|
||||||
|
self.state = self.state.withUpdatingBirthDate(TelegramBirthday(day: 1, month: 1, year: nil))
|
||||||
|
} else if self.state.updatingBirthDate == .some(nil) {
|
||||||
self.state = self.state.withUpdatingBirthDate(TelegramBirthday(day: 1, month: 1, year: nil))
|
self.state = self.state.withUpdatingBirthDate(TelegramBirthday(day: 1, month: 1, year: nil))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3249,6 +3251,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}, openRequestedPeerSelection: { _, _, _, _ in
|
}, openRequestedPeerSelection: { _, _, _, _ in
|
||||||
}, saveMediaToFiles: { _ in
|
}, saveMediaToFiles: { _ in
|
||||||
}, openNoAdsDemo: {
|
}, openNoAdsDemo: {
|
||||||
|
}, openAdsInfo: {
|
||||||
}, displayGiveawayParticipationStatus: { _ in
|
}, displayGiveawayParticipationStatus: { _ in
|
||||||
}, openPremiumStatusInfo: { _, _, _, _ in
|
}, openPremiumStatusInfo: { _, _, _, _ in
|
||||||
}, openRecommendedChannelContextMenu: { _, _, _ in
|
}, openRecommendedChannelContextMenu: { _, _, _ in
|
||||||
|
@ -122,6 +122,7 @@ import AudioWaveform
|
|||||||
import PeerNameColorScreen
|
import PeerNameColorScreen
|
||||||
import ChatEmptyNode
|
import ChatEmptyNode
|
||||||
import ChatMediaInputStickerGridItem
|
import ChatMediaInputStickerGridItem
|
||||||
|
import AdsInfoScreen
|
||||||
|
|
||||||
public enum ChatControllerPeekActions {
|
public enum ChatControllerPeekActions {
|
||||||
case standard
|
case standard
|
||||||
@ -4438,6 +4439,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
self.push(controller)
|
self.push(controller)
|
||||||
|
}, openAdsInfo: { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.push(AdsInfoScreen(context: self.context))
|
||||||
}, displayGiveawayParticipationStatus: { [weak self] messageId in
|
}, displayGiveawayParticipationStatus: { [weak self] messageId in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
|
@ -169,6 +169,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}, openRequestedPeerSelection: { _, _, _, _ in
|
}, openRequestedPeerSelection: { _, _, _, _ in
|
||||||
}, saveMediaToFiles: { _ in
|
}, saveMediaToFiles: { _ in
|
||||||
}, openNoAdsDemo: {
|
}, openNoAdsDemo: {
|
||||||
|
}, openAdsInfo: {
|
||||||
}, displayGiveawayParticipationStatus: { _ in
|
}, displayGiveawayParticipationStatus: { _ in
|
||||||
}, openPremiumStatusInfo: { _, _, _, _ in
|
}, openPremiumStatusInfo: { _, _, _, _ in
|
||||||
}, openRecommendedChannelContextMenu: { _, _, _ in
|
}, openRecommendedChannelContextMenu: { _, _, _ in
|
||||||
|
@ -1756,6 +1756,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}, openRequestedPeerSelection: { _, _, _, _ in
|
}, openRequestedPeerSelection: { _, _, _, _ in
|
||||||
}, saveMediaToFiles: { _ in
|
}, saveMediaToFiles: { _ in
|
||||||
}, openNoAdsDemo: {
|
}, openNoAdsDemo: {
|
||||||
|
}, openAdsInfo: {
|
||||||
}, displayGiveawayParticipationStatus: { _ in
|
}, displayGiveawayParticipationStatus: { _ in
|
||||||
}, openPremiumStatusInfo: { _, _, _, _ in
|
}, openPremiumStatusInfo: { _, _, _, _ in
|
||||||
}, openRecommendedChannelContextMenu: { _, _, _ in
|
}, openRecommendedChannelContextMenu: { _, _, _ in
|
||||||
|
Loading…
x
Reference in New Issue
Block a user