From 70ae305e992e35761848f23a625c01fabb9c055b Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 30 Apr 2022 03:52:31 +0400 Subject: [PATCH] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/Node/ChatListItem.swift | 8 +- .../ContextUI/Sources/ContextController.swift | 4 +- ...tControllerExtractedPresentationNode.swift | 24 +++ .../ContextUI/Sources/PeekController.swift | 2 + .../DeviceAccess/Sources/DeviceAccess.swift | 22 +- .../Display/Source/ImmediateTextNode.swift | 20 +- submodules/Display/Source/NavigationBar.swift | 8 + submodules/Display/Source/TextNode.swift | 27 +-- .../Sources/ReactionSelectionNode.swift | 4 +- .../StickerPackPreviewControllerNode.swift | 2 +- .../Sources/StickerPackPreviewGridItem.swift | 2 +- .../Sources/StickerPackScreen.swift | 8 +- .../Sources/CallRatingController.swift | 48 ++++- .../Sources/State/AvailableReactions.swift | 6 +- .../Sources/TelegramEngine/Peers/Peer.swift | 4 + .../Sources/Utils/PeerUtils.swift | 9 + .../Resources/PresentationResourceKey.swift | 2 + .../Resources/PresentationResourcesChat.swift | 50 ++++- .../PresentationResourcesChatList.swift | 26 +++ .../Contents.json | 0 .../premiumbadge_16.pdf | 0 .../PremiumIcon.imageset/Contents.json | 2 +- .../PremiumIcon.imageset/premium_24 (2).pdf | 97 +++++++++ .../PremiumIcon.imageset/premiumbadge_20.pdf | 97 --------- .../1.pdf | Bin .../Contents.json | 0 .../Contents.json | 2 +- .../addreactions2_32.pdf | Bin 0 -> 1854 bytes .../StickerIcon.imageset/addreactions_32.pdf | 201 ------------------ .../TelegramUI/Sources/ChatController.swift | 29 ++- .../Sources/ChatControllerNode.swift | 13 +- .../TelegramUI/Sources/ChatEmptyNode.swift | 24 ++- .../TelegramUI/Sources/ChatLoadingNode.swift | 4 + .../Sources/ChatMediaInputNode.swift | 2 +- .../ChatMediaInputStickerGridItem.swift | 2 +- .../TelegramUI/Sources/ChatTitleView.swift | 61 ++++-- .../PeerInfoScreenLabeledValueItem.swift | 86 +++++--- .../Sources/PeerInfo/PeerInfoHeaderNode.swift | 34 ++- .../Sources/TelegramRootController.swift | 2 + .../WebUI/Sources/WebAppController.swift | 2 +- 41 files changed, 521 insertions(+), 415 deletions(-) rename submodules/TelegramUI/Images.xcassets/Chat List/{PremiumIcon.imageset => PeerPremiumIcon.imageset}/Contents.json (100%) rename submodules/TelegramUI/Images.xcassets/Chat List/{PremiumIcon.imageset => PeerPremiumIcon.imageset}/premiumbadge_16.pdf (100%) create mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/premium_24 (2).pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/premiumbadge_20.pdf rename submodules/TelegramUI/Images.xcassets/Premium/{ReactionIcon.imageset => BackgroundIcon.imageset}/1.pdf (100%) rename submodules/TelegramUI/Images.xcassets/Premium/{ReactionIcon.imageset => BackgroundIcon.imageset}/Contents.json (100%) rename submodules/TelegramUI/Images.xcassets/Premium/{StickerIcon.imageset => ForegroundIcon.imageset}/Contents.json (74%) create mode 100644 submodules/TelegramUI/Images.xcassets/Premium/ForegroundIcon.imageset/addreactions2_32.pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Premium/StickerIcon.imageset/addreactions_32.pdf diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index e0a50eb07b..2637c32c50 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7542,3 +7542,5 @@ Sorry for the inconvenience."; "Premium.Reactions.Description" = "Unlock additional reactions by subscribing to Telegram Premium."; "Premium.Reactions.Proceed" = "Unlock Additional Reactions"; + +"AccessDenied.LocationPreciseDenied" = "To share your specific location in this chat, please go to Settings > Privacy > Location Services > Telegram and set Precise Location to On."; diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 963f7f0b19..76dbdb1cb7 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -1379,6 +1379,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } else if peer.isVerified { currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme) credibilityIconOffset = 3.0 + } else if peer.isPremium { + currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme) + credibilityIconOffset = 2.0 } } default: @@ -1394,6 +1397,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { } else if peer.isVerified { currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme) credibilityIconOffset = 3.0 + } else if peer.isPremium { + currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme) + credibilityIconOffset = 2.0 } } } @@ -1762,7 +1768,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { if let currentMutedIconImage = currentMutedIconImage { strongSelf.mutedIconNode.image = currentMutedIconImage strongSelf.mutedIconNode.isHidden = false - transition.updateFrame(node: strongSelf.mutedIconNode, frame: CGRect(origin: CGPoint(x: nextTitleIconOrigin - 4.0, y: contentRect.origin.y - 2.0), size: currentMutedIconImage.size)) + transition.updateFrame(node: strongSelf.mutedIconNode, frame: CGRect(origin: CGPoint(x: nextTitleIconOrigin - 5.0, y: contentRect.origin.y - 3.0 + UIScreenPixel), size: currentMutedIconImage.size)) nextTitleIconOrigin += currentMutedIconImage.size.width + 1.0 } else { strongSelf.mutedIconNode.image = nil diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index d57cd8d174..bf6ffef5f8 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -14,6 +14,7 @@ private let animationDurationFactor: Double = 1.0 public protocol ContextControllerProtocol: AnyObject { var useComplexItemsTransitionAnimation: Bool { get set } var immediateItemsTransitionAnimation: Bool { get set } + var getOverlayViews: (() -> [UIView])? { get set } func getActionsMinHeight() -> ContextController.ActionsHeight? func setItems(_ items: Signal, minHeight: ContextController.ActionsHeight?) @@ -1238,7 +1239,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi } if animateOutToItem, let originalProjectedContentViewFrame = self.originalProjectedContentViewFrame { - let localSourceFrame = self.view.convert(CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalProjectedContentViewFrame.1.minY), size: CGSize(width: originalProjectedContentViewFrame.1.width, height: originalProjectedContentViewFrame.1.height)), to: self.scrollNode.view) self.actionsContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: localSourceFrame.center.x - self.actionsContainerNode.position.x, y: localSourceFrame.center.y - self.actionsContainerNode.position.y), duration: transitionDuration * animationDurationFactor, timingFunction: transitionCurve.timingFunction, removeOnCompletion: false, additive: true) @@ -2267,6 +2267,8 @@ public final class ContextController: ViewController, StandalonePresentableContr public var reactionSelected: ((ReactionContextItem, Bool) -> Void)? + public var getOverlayViews: (() -> [UIView])? + public init(account: Account, presentationData: PresentationData, source: ContextContentSource, items: Signal, recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil, workaroundUseLegacyImplementation: Bool = false) { self.account = account self.presentationData = presentationData diff --git a/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift b/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift index fb6c35b8dd..bec09596c1 100644 --- a/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerExtractedPresentationNode.swift @@ -638,6 +638,18 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo } } } + + if let overlayViews = self.getController()?.getOverlayViews?(), !overlayViews.isEmpty { + for view in overlayViews { + if let snapshotView = view.snapshotView(afterScreenUpdates: false) { + snapshotView.frame = view.convert(view.bounds, to: nil) + self.view.addSubview(snapshotView) + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + } + } + } case let .animateOut(result, completion): let duration: Double let timingFunction: String @@ -785,6 +797,18 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo if let reactionContextNode = self.reactionContextNode { reactionContextNode.animateOut(to: currentContentScreenFrame, animatingOutToReaction: self.reactionContextNodeIsAnimatingOut) } + + if let overlayViews = self.getController()?.getOverlayViews?(), !overlayViews.isEmpty { + for view in overlayViews { + if let snapshotView = view.snapshotView(afterScreenUpdates: false) { + snapshotView.frame = view.convert(view.bounds, to: nil) + self.view.addSubview(snapshotView) + snapshotView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + } + } + } case .none: if animateReactionsIn, let reactionContextNode = self.reactionContextNode { reactionContextNode.animateIn(from: contentRect) diff --git a/submodules/ContextUI/Sources/PeekController.swift b/submodules/ContextUI/Sources/PeekController.swift index 312e8340b8..78950898b7 100644 --- a/submodules/ContextUI/Sources/PeekController.swift +++ b/submodules/ContextUI/Sources/PeekController.swift @@ -64,6 +64,8 @@ public final class PeekController: ViewController, ContextControllerProtocol { public var visibilityUpdated: ((Bool) -> Void)? + public var getOverlayViews: (() -> [UIView])? + private var animatedIn = false public init(presentationData: PresentationData, content: PeekControllerContent, sourceNode: @escaping () -> ASDisplayNode?) { diff --git a/submodules/DeviceAccess/Sources/DeviceAccess.swift b/submodules/DeviceAccess/Sources/DeviceAccess.swift index dd0382288d..4751691d08 100644 --- a/submodules/DeviceAccess/Sources/DeviceAccess.swift +++ b/submodules/DeviceAccess/Sources/DeviceAccess.swift @@ -378,9 +378,29 @@ public final class DeviceAccess { } case let .location(locationSubject): let status = CLLocationManager.authorizationStatus() + let hasPreciseLocation: Bool + if #available(iOS 14.0, *) { + if case .fullAccuracy = CLLocationManager().accuracyAuthorization { + hasPreciseLocation = true + } else { + hasPreciseLocation = false + } + } else { + hasPreciseLocation = true + } switch status { case .authorizedAlways: - completion(true) + if case .live = locationSubject, !hasPreciseLocation { + completion(false) + if let presentationData = presentationData { + let text = presentationData.strings.AccessDenied_LocationPreciseDenied + present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: { + openSettings() + })]), nil) + } + } else { + completion(true) + } case .authorizedWhenInUse: switch locationSubject { case .send, .tracking: diff --git a/submodules/Display/Source/ImmediateTextNode.swift b/submodules/Display/Source/ImmediateTextNode.swift index a999b324f1..612fb81758 100644 --- a/submodules/Display/Source/ImmediateTextNode.swift +++ b/submodules/Display/Source/ImmediateTextNode.swift @@ -4,6 +4,7 @@ import UIKit public struct ImmediateTextNodeLayoutInfo { public let size: CGSize public let truncated: Bool + public let numberOfLines: Int } public class ImmediateTextNode: TextNode { @@ -18,8 +19,7 @@ public class ImmediateTextNode: TextNode { public var textStroke: (UIColor, CGFloat)? public var cutout: TextNodeCutout? public var displaySpoilers = false - public var countIfMoreThanOneLineOverMaximum = false - + public var truncationMode: NSLineBreakMode { get { switch self.truncationType { @@ -91,7 +91,7 @@ public class ImmediateTextNode: TextNode { self.constrainedSize = constrainedSize let makeLayout = TextNode.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke, displaySpoilers: self.displaySpoilers, countIfMoreThanOneLineOverMaximum: self.countIfMoreThanOneLineOverMaximum)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke, displaySpoilers: self.displaySpoilers)) let _ = apply() if layout.numberOfLines > 1 { self.trailingLineWidth = layout.trailingLineWidth @@ -105,16 +105,16 @@ public class ImmediateTextNode: TextNode { self.constrainedSize = constrainedSize let makeLayout = TextNode.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers, countIfMoreThanOneLineOverMaximum: self.countIfMoreThanOneLineOverMaximum)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers)) let _ = apply() - return ImmediateTextNodeLayoutInfo(size: layout.size, truncated: layout.truncated) + return ImmediateTextNodeLayoutInfo(size: layout.size, truncated: layout.truncated, numberOfLines: layout.numberOfLines) } public func updateLayoutFullInfo(_ constrainedSize: CGSize) -> TextNodeLayout { self.constrainedSize = constrainedSize let makeLayout = TextNode.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers, countIfMoreThanOneLineOverMaximum: self.countIfMoreThanOneLineOverMaximum)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers)) let _ = apply() return layout } @@ -287,7 +287,7 @@ public class ImmediateTextView: TextView { self.constrainedSize = constrainedSize let makeLayout = TextView.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke, displaySpoilers: self.displaySpoilers, countIfMoreThanOneLineOverMaximum: false)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, textShadowColor: self.textShadowColor, textStroke: self.textStroke, displaySpoilers: self.displaySpoilers)) let _ = apply() if layout.numberOfLines > 1 { self.trailingLineWidth = layout.trailingLineWidth @@ -301,16 +301,16 @@ public class ImmediateTextView: TextView { self.constrainedSize = constrainedSize let makeLayout = TextView.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers, countIfMoreThanOneLineOverMaximum: false)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers)) let _ = apply() - return ImmediateTextNodeLayoutInfo(size: layout.size, truncated: layout.truncated) + return ImmediateTextNodeLayoutInfo(size: layout.size, truncated: layout.truncated, numberOfLines: layout.numberOfLines) } public func updateLayoutFullInfo(_ constrainedSize: CGSize) -> TextNodeLayout { self.constrainedSize = constrainedSize let makeLayout = TextView.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers, countIfMoreThanOneLineOverMaximum: false)) + let (layout, apply) = makeLayout(TextNodeLayoutArguments(attributedString: self.attributedText, backgroundColor: nil, maximumNumberOfLines: self.maximumNumberOfLines, truncationType: self.truncationType, constrainedSize: constrainedSize, alignment: self.textAlignment, verticalAlignment: self.verticalAlignment, lineSpacing: self.lineSpacing, cutout: self.cutout, insets: self.insets, displaySpoilers: self.displaySpoilers)) let _ = apply() return layout } diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 5c723deef3..5ce6f8cadf 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -123,6 +123,14 @@ public final class NavigationBackgroundNode: ASDisplayNode { private let backgroundNode: ASDisplayNode private var validLayout: (CGSize, CGFloat)? + + public var backgroundCornerRadius: CGFloat { + if let (_, cornerRadius) = self.validLayout { + return cornerRadius + } else { + return 0.0 + } + } public init(color: UIColor, enableBlur: Bool = true) { self._color = .clear diff --git a/submodules/Display/Source/TextNode.swift b/submodules/Display/Source/TextNode.swift index abe8e3cc07..64f1cb3858 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -132,9 +132,8 @@ public final class TextNodeLayoutArguments { public let textShadowColor: UIColor? public let textStroke: (UIColor, CGFloat)? public let displaySpoilers: Bool - public let countIfMoreThanOneLineOverMaximum: Bool - public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, minimumNumberOfLines: Int = 0, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, verticalAlignment: TextVerticalAlignment = .top, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil, textStroke: (UIColor, CGFloat)? = nil, displaySpoilers: Bool = false, countIfMoreThanOneLineOverMaximum: Bool = false) { + public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, minimumNumberOfLines: Int = 0, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, verticalAlignment: TextVerticalAlignment = .top, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil, textStroke: (UIColor, CGFloat)? = nil, displaySpoilers: Bool = false) { self.attributedString = attributedString self.backgroundColor = backgroundColor self.minimumNumberOfLines = minimumNumberOfLines @@ -150,7 +149,6 @@ public final class TextNodeLayoutArguments { self.textShadowColor = textShadowColor self.textStroke = textStroke self.displaySpoilers = displaySpoilers - self.countIfMoreThanOneLineOverMaximum = countIfMoreThanOneLineOverMaximum } } @@ -179,9 +177,8 @@ public final class TextNodeLayout: NSObject { public let hasRTL: Bool public let spoilers: [(NSRange, CGRect)] public let spoilerWords: [(NSRange, CGRect)] - public let hasMoreThanOneLineOverMaximum: Bool? - fileprivate init(attributedString: NSAttributedString?, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, explicitAlignment: NSTextAlignment, resolvedAlignment: NSTextAlignment, verticalAlignment: TextVerticalAlignment, lineSpacing: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, size: CGSize, rawTextSize: CGSize, truncated: Bool, firstLineOffset: CGFloat, lines: [TextNodeLine], blockQuotes: [TextNodeBlockQuote], backgroundColor: UIColor?, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?, displaySpoilers: Bool, hasMoreThanOneLineOverMaximum: Bool?) { + fileprivate init(attributedString: NSAttributedString?, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, explicitAlignment: NSTextAlignment, resolvedAlignment: NSTextAlignment, verticalAlignment: TextVerticalAlignment, lineSpacing: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, size: CGSize, rawTextSize: CGSize, truncated: Bool, firstLineOffset: CGFloat, lines: [TextNodeLine], blockQuotes: [TextNodeBlockQuote], backgroundColor: UIColor?, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?, displaySpoilers: Bool) { self.attributedString = attributedString self.maximumNumberOfLines = maximumNumberOfLines self.truncationType = truncationType @@ -225,7 +222,6 @@ public final class TextNodeLayout: NSObject { self.hasRTL = hasRTL self.spoilers = spoilers self.spoilerWords = spoilerWords - self.hasMoreThanOneLineOverMaximum = hasMoreThanOneLineOverMaximum } public func areLinesEqual(to other: TextNodeLayout) -> Bool { @@ -896,9 +892,6 @@ public class TextNode: ASDisplayNode { static func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, verticalAlignment: TextVerticalAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?, displaySpoilers: Bool) -> TextNodeLayout { if let attributedString = attributedString { - if attributedString.string.hasPrefix("Д") { - print() - } let stringLength = attributedString.length let font: CTFont @@ -935,7 +928,7 @@ public class TextNode: ASDisplayNode { var maybeTypesetter: CTTypesetter? maybeTypesetter = CTTypesetterCreateWithAttributedString(attributedString as CFAttributedString) if maybeTypesetter == nil { - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers, hasMoreThanOneLineOverMaximum: nil) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers) } let typesetter = maybeTypesetter! @@ -951,9 +944,7 @@ public class TextNode: ASDisplayNode { var bottomCutoutEnabled = false var bottomCutoutSize = CGSize() - - let hasMoreThanOneLineOverMaximum: Bool? = nil - + if let topLeft = cutout?.topLeft { cutoutMinY = -fontLineSpacing cutoutMaxY = topLeft.height + fontLineSpacing @@ -1268,9 +1259,9 @@ public class TextNode: ASDisplayNode { } } - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers, hasMoreThanOneLineOverMaximum: hasMoreThanOneLineOverMaximum) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers) } else { - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: alignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers, hasMoreThanOneLineOverMaximum: nil) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: alignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers) } } @@ -1594,7 +1585,7 @@ open class TextView: UIView { var maybeTypesetter: CTTypesetter? maybeTypesetter = CTTypesetterCreateWithAttributedString(attributedString as CFAttributedString) if maybeTypesetter == nil { - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers, hasMoreThanOneLineOverMaximum: nil) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers) } let typesetter = maybeTypesetter! @@ -1925,9 +1916,9 @@ open class TextView: UIView { } } - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers, hasMoreThanOneLineOverMaximum: nil) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: resolvedAlignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers) } else { - return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: alignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers, hasMoreThanOneLineOverMaximum: nil) + return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, explicitAlignment: alignment, resolvedAlignment: alignment, verticalAlignment: verticalAlignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor, textStroke: textStroke, displaySpoilers: displaySpoilers) } } diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift index 5216d1220a..28ff9eb170 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift @@ -316,9 +316,9 @@ final class PremiumReactionsNode: ASDisplayNode, ReactionItemNode { self.addSubnode(self.imageNode) if theme.overallDarkAppearance { - self.imageNode.image = generateTintedImage(image: UIImage(bundleImageName: "Premium/ReactionIcon"), color: .white) + self.imageNode.image = generateTintedImage(image: UIImage(bundleImageName: "Premium/BackgroundIcon"), color: .white) } else { - self.imageNode.image = UIImage(bundleImageName: "Premium/ReactionIcon") + self.imageNode.image = UIImage(bundleImageName: "Premium/BackgroundIcon") } } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift index 711721e617..f3b65ebb4d 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -204,7 +204,7 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol return strongSelf.context.account.postbox.transaction { transaction -> (Bool, Bool) in let isStarred = getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) var hasPremium = false - if let peer = transaction.getPeer(accountPeerId) as? TelegramUser, peer.flags.contains(.isPremium) { + if let peer = transaction.getPeer(accountPeerId) as? TelegramUser, peer.isPremium { hasPremium = true } return (isStarred, hasPremium) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift index bab68cb1cf..cfa8936fa4 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift @@ -174,7 +174,7 @@ final class StickerPackPreviewGridItemNode: GridItemNode { lockBackground = UIImageView() lockBackground.clipsToBounds = true lockBackground.isUserInteractionEnabled = false - lockBackground.image = UIImage(bundleImageName: "Premium/StickerIcon") + lockBackground.image = PresentationResourcesChat.chatInputMediaStickerGridPremiumIcon(theme) self.lockBackground = lockBackground self.view.addSubview(lockBackground) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 5c71200690..3bde5c806c 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -177,8 +177,8 @@ private final class StickerPackContainer: ASDisplayNode { self.addSubnode(self.backgroundNode) self.addSubnode(self.gridNode) - self.addSubnode(self.actionAreaBackgroundNode) - self.addSubnode(self.actionAreaSeparatorNode) +// self.addSubnode(self.actionAreaBackgroundNode) +// self.addSubnode(self.actionAreaSeparatorNode) self.addSubnode(self.buttonNode) self.addSubnode(self.titleBackgroundnode) @@ -294,7 +294,7 @@ private final class StickerPackContainer: ASDisplayNode { return } var hasPremium = false - if case let .user(user) = peer, user.flags.contains(.isPremium) { + if let peer = peer, peer.isPremium { hasPremium = true } strongSelf.updateStickerPackContents(contents, hasPremium: hasPremium) @@ -337,7 +337,7 @@ private final class StickerPackContainer: ASDisplayNode { return strongSelf.context.account.postbox.transaction { transaction -> (Bool, Bool) in let isStarred = getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) var hasPremium = false - if let peer = transaction.getPeer(accountPeerId) as? TelegramUser, peer.flags.contains(.isPremium) { + if let peer = transaction.getPeer(accountPeerId) as? TelegramUser, peer.isPremium { hasPremium = true } return (isStarred, hasPremium) diff --git a/submodules/TelegramCallsUI/Sources/CallRatingController.swift b/submodules/TelegramCallsUI/Sources/CallRatingController.swift index b2b89b7630..82e0a51828 100644 --- a/submodules/TelegramCallsUI/Sources/CallRatingController.swift +++ b/submodules/TelegramCallsUI/Sources/CallRatingController.swift @@ -17,6 +17,7 @@ private final class CallRatingAlertContentNode: AlertContentNode { var rating: Int? private let titleNode: ASTextNode + private var starContainerNode: ASDisplayNode private let starNodes: [ASButtonNode] private let actionNodesSeparator: ASDisplayNode @@ -38,6 +39,8 @@ private final class CallRatingAlertContentNode: AlertContentNode { self.titleNode = ASTextNode() self.titleNode.maximumNumberOfLines = 3 + self.starContainerNode = ASDisplayNode() + var starNodes: [ASButtonNode] = [] for _ in 0 ..< 5 { starNodes.append(ASButtonNode()) @@ -65,10 +68,12 @@ private final class CallRatingAlertContentNode: AlertContentNode { self.addSubnode(self.titleNode) + self.addSubnode(self.starContainerNode) + for node in self.starNodes { node.addTarget(self, action: #selector(self.starPressed(_:)), forControlEvents: .touchDown) node.addTarget(self, action: #selector(self.starReleased(_:)), forControlEvents: .touchUpInside) - self.addSubnode(node) + self.starContainerNode.addSubnode(node) } self.addSubnode(self.actionNodesSeparator) @@ -88,6 +93,44 @@ private final class CallRatingAlertContentNode: AlertContentNode { self.disposable.dispose() } + override func didLoad() { + super.didLoad() + + self.starContainerNode.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) + } + + @objc func panGesture(_ gestureRecognizer: UIPanGestureRecognizer) { + let location = gestureRecognizer.location(in: self.starContainerNode.view) + var selectedNode: ASButtonNode? + for node in self.starNodes { + if node.frame.contains(location) { + selectedNode = node + break + } + } + if let selectedNode = selectedNode { + switch gestureRecognizer.state { + case .began, .changed: + self.starPressed(selectedNode) + case .ended: + self.starReleased(selectedNode) + case .cancelled: + self.resetStars() + default: + break + } + } else { + self.resetStars() + } + } + + private func resetStars() { + for i in 0 ..< self.starNodes.count { + let node = self.starNodes[i] + node.isSelected = false + } + } + @objc func starPressed(_ sender: ASButtonNode) { if let index = self.starNodes.firstIndex(of: sender) { self.rating = index + 1 @@ -182,9 +225,10 @@ private final class CallRatingAlertContentNode: AlertContentNode { let starSize = CGSize(width: 42.0, height: 38.0) let starsOrigin = floorToScreenPixels((resultWidth - starSize.width * 5.0) / 2.0) + self.starContainerNode.frame = CGRect(origin: CGPoint(x: starsOrigin, y: origin.y), size: CGSize(width: starSize.width * CGFloat(self.starNodes.count), height: starSize.height)) for i in 0 ..< self.starNodes.count { let node = self.starNodes[i] - transition.updateFrame(node: node, frame: CGRect(x: starsOrigin + 42.0 * CGFloat(i), y: origin.y, width: starSize.width, height: starSize.height)) + transition.updateFrame(node: node, frame: CGRect(x: starSize.width * CGFloat(i), y: 0.0, width: starSize.width, height: starSize.height)) } origin.y += titleSize.height diff --git a/submodules/TelegramCore/Sources/State/AvailableReactions.swift b/submodules/TelegramCore/Sources/State/AvailableReactions.swift index 74e7a1857a..4d9907e4dd 100644 --- a/submodules/TelegramCore/Sources/State/AvailableReactions.swift +++ b/submodules/TelegramCore/Sources/State/AvailableReactions.swift @@ -155,7 +155,7 @@ public final class AvailableReactions: Equatable, Codable { } private enum CodingKeys: String, CodingKey { - case hash + case newHash case reactions } @@ -183,14 +183,14 @@ public final class AvailableReactions: Equatable, Codable { public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) - self.hash = try container.decode(Int32.self, forKey: .hash) + self.hash = try container.decodeIfPresent(Int32.self, forKey: .newHash) ?? 0 self.reactions = try container.decode([Reaction].self, forKey: .reactions) } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(self.hash, forKey: .hash) + try container.encode(self.hash, forKey: .newHash) try container.encode(self.reactions, forKey: .reactions) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift index c8e13058f8..8e8ae43c49 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift @@ -395,6 +395,10 @@ public extension EnginePeer { var isVerified: Bool { return self._asPeer().isVerified } + + var isPremium: Bool { + return self._asPeer().isPremium + } var isService: Bool { if case let .user(peer) = self { diff --git a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift index 0837d28fbf..31207ee4b0 100644 --- a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift @@ -154,6 +154,15 @@ public extension Peer { } } + var isPremium: Bool { + switch self { + case let user as TelegramUser: + return user.flags.contains(.isPremium) + default: + return false + } + } + var isCopyProtectionEnabled: Bool { switch self { case let group as TelegramGroup: diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift index a5ab1c0e80..49cfc98ef9 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift @@ -85,6 +85,7 @@ public enum PresentationResourceKey: Int32 { case chatListBadgeBackgroundPinned case chatListMutedIcon case chatListVerifiedIcon + case chatListPremiumIcon case chatListScamRegularIcon case chatListScamOutgoingIcon case chatListScamServiceIcon @@ -165,6 +166,7 @@ public enum PresentationResourceKey: Int32 { case chatInputMediaPanelTrendingGifsIcon case chatInputMediaPanelStickersModeIcon case chatInputMediaPanelPremiumIcon + case chatInputMediaStickerGridPremiumIcon case chatInputButtonPanelButtonImage case chatInputButtonPanelButtonHighlightedImage diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift index e8de1d49cb..d0b57b7c92 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift @@ -294,13 +294,59 @@ public struct PresentationResourcesChat { return theme.image(PresentationResourceKey.chatInputMediaPanelPremiumIcon.rawValue, { theme in return generateImage(CGSize(width: 44.0, height: 42.0), contextGenerator: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) - if let image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PremiumIcon"), color: theme.chat.inputMediaPanel.panelIconColor) { - context.draw(image.cgImage!, in: CGRect(origin: CGPoint(x: floor((size.width - image.size.width) / 2.0), y: floor((size.height - image.size.height) / 2.0)), size: image.size)) + if let image = UIImage(bundleImageName: "Peer Info/PremiumIcon") { + if let cgImage = image.cgImage { + context.clip(to: CGRect(origin: .zero, size: size), mask: cgImage) + } + + let colorsArray: [CGColor] = [ + UIColor(rgb: 0x418eff).cgColor, + UIColor(rgb: 0x418eff).cgColor, + UIColor(rgb: 0xfc7ebd).cgColor, + UIColor(rgb: 0xfc7ebd).cgColor + ] + var locations: [CGFloat] = [0.0, 0.35, 0.65, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: size.height), options: CGGradientDrawingOptions()) } }) }) } + public static func chatInputMediaStickerGridPremiumIcon(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.chatInputMediaStickerGridPremiumIcon.rawValue, { theme in + return generateImage(CGSize(width: 32.0, height: 32.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + if let backgroundImage = UIImage(bundleImageName: "Premium/BackgroundIcon"), let foregroundImage = UIImage(bundleImageName: "Premium/ForegroundIcon") { + context.saveGState() + if let cgImage = backgroundImage.cgImage { + context.clip(to: CGRect(origin: .zero, size: size), mask: cgImage) + } + + let colorsArray: [CGColor] = [ + UIColor(rgb: 0x418eff).cgColor, + UIColor(rgb: 0x418eff).cgColor, + UIColor(rgb: 0xfc7ebd).cgColor, + UIColor(rgb: 0xfc7ebd).cgColor + ] + var locations: [CGFloat] = [0.0, 0.35, 0.65, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: size.height), options: CGGradientDrawingOptions()) + + context.restoreGState() + + if let cgImage = foregroundImage.cgImage { + context.clip(to: CGRect(origin: .zero, size: size), mask: cgImage) + } + context.setFillColor(UIColor.white.cgColor) + context.fill(CGRect(origin: CGPoint(), size: size)) + } + }) + }) + } + public static func chatInputMediaPanelRecentStickersIcon(_ theme: PresentationTheme) -> UIImage? { return theme.image(PresentationResourceKey.chatInputMediaPanelRecentStickersIconImage.rawValue, { theme in return generateImage(CGSize(width: 42.0, height: 42.0), contextGenerator: { size, context in diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChatList.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChatList.swift index 0fa18c0be4..bdbf154da3 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChatList.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChatList.swift @@ -228,6 +228,32 @@ public struct PresentationResourcesChatList { return UIImage(bundleImageName: "Chat List/PeerVerifiedIcon")?.precomposed() }) } + + public static func premiumIcon(_ theme: PresentationTheme) -> UIImage? { + return theme.image(PresentationResourceKey.chatListPremiumIcon.rawValue, { theme in + if let image = UIImage(bundleImageName: "Chat List/PeerPremiumIcon") { + return generateImage(image.size, contextGenerator: { size, context in + if let cgImage = image.cgImage { + context.clear(CGRect(origin: CGPoint(), size: size)) + context.clip(to: CGRect(origin: .zero, size: size), mask: cgImage) + + let colorsArray: [CGColor] = [ + UIColor(rgb: 0x418eff).cgColor, + UIColor(rgb: 0x418eff).cgColor, + UIColor(rgb: 0xfc7ebd).cgColor, + UIColor(rgb: 0xfc7ebd).cgColor + ] + var locations: [CGFloat] = [0.0, 0.35, 0.65, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: size.height), options: CGGradientDrawingOptions()) + } + }, opaque: false) + } else { + return nil + } + }) + } public static func scamIcon(_ theme: PresentationTheme, strings: PresentationStrings, type: ScamIconType) -> UIImage? { let key: PresentationResourceKey diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/PremiumIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat List/PeerPremiumIcon.imageset/Contents.json similarity index 100% rename from submodules/TelegramUI/Images.xcassets/Chat List/PremiumIcon.imageset/Contents.json rename to submodules/TelegramUI/Images.xcassets/Chat List/PeerPremiumIcon.imageset/Contents.json diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/PremiumIcon.imageset/premiumbadge_16.pdf b/submodules/TelegramUI/Images.xcassets/Chat List/PeerPremiumIcon.imageset/premiumbadge_16.pdf similarity index 100% rename from submodules/TelegramUI/Images.xcassets/Chat List/PremiumIcon.imageset/premiumbadge_16.pdf rename to submodules/TelegramUI/Images.xcassets/Chat List/PeerPremiumIcon.imageset/premiumbadge_16.pdf diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/Contents.json index 921409e9d8..c89c9f61c4 100644 --- a/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "premiumbadge_20.pdf", + "filename" : "premium_24 (2).pdf", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/premium_24 (2).pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/premium_24 (2).pdf new file mode 100644 index 0000000000..8fe75f92e4 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/premium_24 (2).pdf @@ -0,0 +1,97 @@ +%PDF-1.7 + +1 0 obj + << >> +endobj + +2 0 obj + << /Length 3 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 1.565002 2.396484 cm +0.000000 0.000000 0.000000 scn +9.882594 3.317978 m +5.183870 0.439518 l +4.695292 0.140213 4.056584 0.293650 3.757278 0.782228 c +3.611097 1.020851 3.567514 1.308409 3.636422 1.579630 c +4.363782 4.442544 l +4.626348 5.476007 5.333546 6.339901 6.294793 6.801413 c +11.420867 9.262531 l +11.659847 9.377270 11.760565 9.664015 11.645826 9.902994 c +11.552906 10.096530 11.342772 10.204829 11.131232 10.168206 c +5.425254 9.180357 l +4.265362 8.979550 3.075904 9.299845 2.173681 10.055932 c +0.371115 11.566533 l +-0.068036 11.934555 -0.125698 12.588898 0.242323 13.028049 c +0.421316 13.241636 0.678710 13.374235 0.956533 13.395977 c +6.463908 13.826983 l +6.852989 13.857433 7.192064 14.103661 7.341429 14.464218 c +9.466071 19.592974 l +9.685358 20.122318 10.292244 20.373671 10.821589 20.154385 c +11.075764 20.049089 11.277705 19.847147 11.382999 19.592974 c +13.507642 14.464218 l +13.657006 14.103661 13.996081 13.857433 14.385162 13.826983 c +19.922798 13.393608 l +20.494020 13.348906 20.920849 12.849598 20.876144 12.278376 c +20.854639 12.003585 20.724667 11.748647 20.514914 11.569828 c +16.291594 7.969350 l +15.994287 7.715888 15.864580 7.316894 15.956014 6.937058 c +17.254391 1.543314 l +17.388485 0.986258 17.045605 0.425970 16.488548 0.291876 c +16.220879 0.227442 15.938575 0.272047 15.703809 0.415865 c +10.966476 3.317978 l +10.633904 3.521713 10.215167 3.521713 9.882594 3.317978 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1468 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000001558 00000 n +0000001581 00000 n +0000001754 00000 n +0000001828 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1887 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/premiumbadge_20.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/premiumbadge_20.pdf deleted file mode 100644 index 812c7091d1..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Peer Info/PremiumIcon.imageset/premiumbadge_20.pdf +++ /dev/null @@ -1,97 +0,0 @@ -%PDF-1.7 - -1 0 obj - << >> -endobj - -2 0 obj - << /Length 3 0 R >> -stream -/DeviceRGB CS -/DeviceRGB cs -q -1.000000 0.000000 -0.000000 1.000000 1.312988 1.997192 cm -0.000000 0.000000 0.000000 scn -8.235496 2.764818 m -4.319892 0.366102 l -3.912743 0.116680 3.380487 0.244545 3.131065 0.651693 c -3.009248 0.850546 2.972928 1.090177 3.030351 1.316196 c -3.636486 3.701958 l -3.855290 4.563177 4.444622 5.283089 5.245661 5.667681 c -9.517389 7.718613 l -9.716539 7.814228 9.800470 8.053183 9.704855 8.252333 c -9.627422 8.413612 9.452311 8.503861 9.276028 8.473343 c -4.521046 7.650135 l -3.554468 7.482796 2.563253 7.749707 1.811401 8.379781 c -0.309263 9.638615 l --0.056697 9.945299 -0.104749 10.490585 0.201936 10.856544 c -0.351096 11.034534 0.565592 11.145033 0.797111 11.163151 c -5.386590 11.522324 l -5.710824 11.547698 5.993387 11.752888 6.117858 12.053352 c -7.888392 16.327314 l -8.071132 16.768436 8.576871 16.977896 9.017992 16.795156 c -9.229803 16.707413 9.398088 16.539127 9.485833 16.327314 c -11.256369 12.053352 l -11.380839 11.752888 11.663401 11.547698 11.987636 11.522324 c -16.602333 11.161178 l -17.078350 11.123924 17.434040 10.707836 17.396788 10.231817 c -17.378866 10.002825 17.270555 9.790377 17.095762 9.641360 c -13.576328 6.640962 l -13.328572 6.429744 13.220484 6.097248 13.296679 5.780720 c -14.378658 1.285933 l -14.490404 0.821718 14.204671 0.354813 13.740458 0.243067 c -13.517399 0.189373 13.282146 0.226543 13.086508 0.346392 c -9.138731 2.764818 l -8.861588 2.934598 8.512639 2.934598 8.235496 2.764818 c -h -f* -n -Q - -endstream -endobj - -3 0 obj - 1445 -endobj - -4 0 obj - << /Annots [] - /Type /Page - /MediaBox [ 0.000000 0.000000 20.000000 20.000000 ] - /Resources 1 0 R - /Contents 2 0 R - /Parent 5 0 R - >> -endobj - -5 0 obj - << /Kids [ 4 0 R ] - /Count 1 - /Type /Pages - >> -endobj - -6 0 obj - << /Pages 5 0 R - /Type /Catalog - >> -endobj - -xref -0 7 -0000000000 65535 f -0000000010 00000 n -0000000034 00000 n -0000001535 00000 n -0000001558 00000 n -0000001731 00000 n -0000001805 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -1864 -%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Premium/ReactionIcon.imageset/1.pdf b/submodules/TelegramUI/Images.xcassets/Premium/BackgroundIcon.imageset/1.pdf similarity index 100% rename from submodules/TelegramUI/Images.xcassets/Premium/ReactionIcon.imageset/1.pdf rename to submodules/TelegramUI/Images.xcassets/Premium/BackgroundIcon.imageset/1.pdf diff --git a/submodules/TelegramUI/Images.xcassets/Premium/ReactionIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/BackgroundIcon.imageset/Contents.json similarity index 100% rename from submodules/TelegramUI/Images.xcassets/Premium/ReactionIcon.imageset/Contents.json rename to submodules/TelegramUI/Images.xcassets/Premium/BackgroundIcon.imageset/Contents.json diff --git a/submodules/TelegramUI/Images.xcassets/Premium/StickerIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Premium/ForegroundIcon.imageset/Contents.json similarity index 74% rename from submodules/TelegramUI/Images.xcassets/Premium/StickerIcon.imageset/Contents.json rename to submodules/TelegramUI/Images.xcassets/Premium/ForegroundIcon.imageset/Contents.json index 2acd1b3c24..c60ea81e07 100644 --- a/submodules/TelegramUI/Images.xcassets/Premium/StickerIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Premium/ForegroundIcon.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "addreactions_32.pdf", + "filename" : "addreactions2_32.pdf", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Premium/ForegroundIcon.imageset/addreactions2_32.pdf b/submodules/TelegramUI/Images.xcassets/Premium/ForegroundIcon.imageset/addreactions2_32.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a10889d1e3b1243c131903b344a14c9452db17eb GIT binary patch literal 1854 zcmah~X;c$e6b4O;gi4A9w1_=VAct^RGBadh2~@Tq3J5_2+-jBqLoq`q6Ajf0D5%&{ z6+{$hRm3AAP+Tx*rJ`aji&aa|aqwma{JMVjU?l#|j!;T0P zyP|GrE>3hx7uy+p{PhD((z0G)W2KY2<=3N&pC%LLG;n(I6YDSo8b+8|T}b z@eUvMoIPU2s&LFSDxGFgYPo!ALGOd-?DU$m8;NY4xGgsz^H}~>N#&{h%nyxE)J$tMLzZrR zSe>{s+o~d_u+8oR_f4H?f2H4qVd%UtwE*I_165Y$1QA?0y%})-j{MR*y zF0NX)&BjQ7rbjP4bMDHOIw}9 z!_Ue*WVhYIGq3;fu+o1o$1-nAls4@%5hK{#{}WwI@syABhfRfPUxezmnlrv)3^RII z0}aZ{U*_C8)KjAO*)cD`)@r|JORJr|>EQErU$Y|qiaE#eZoky9VXM@LtMLP9URIk) ze7m=cb$eG&U5l|KE;A)3=n|{>Sd8Ylc6eT*_YD2;!Ss&M4m7waQp>F2=3gm{?dTMJ zA8f0?6K-AEX0pY~gp<;snA+qhK2UD=t}G|0?!JTGH78x(6g%sVZD;y&{~@t`n9qXT zTq<;P=NZ?QC%s1oGwO$)F_xduJtyS|u&kjtngr@;Z;x}i)~fD^@1~D0c*PMhGdu2k zELyuEy{JDU{Y>u5uXj-_?~RR)73`r}4NJyxGxhiNB_q#X{Oz=1daBXjrnMp_u2PIO z4Sb^8jqWj8!Y=bb5qh6qxlc5sq5XoiRB#jpTMvjtGyn%ziogZn2KWIKaOF~XhYblg z;2mCLcCZOMfV(&)83)`5X#x(|05#Z+kdnBHg0GJEc^IxxO8p5fSOy^kxMTFS!k`;K zs3@qc2J}HOdMX5ygeG}XNTVJM=y;S-&@U-fsgr3>@|1Bn1W=>~A72GPtw4OOQjSZ4 z{b_JC6RreT6B<&Es{vgP$)vpKh{q4BH+iY)cex9d3N?(MPF*q)yM|74k^#Xa0}&*l z(8%HO#*s^vBmq!2RN#gH&T5KER(o+_aUq&ON|RSB4fwM-U83ceuu&&V+;@jbk2A2TmbxY(k8-;qC|bplx~z z{?9(`8|n$6K>>7%c^de@HH4`oRDm>qIDuXmf?)^`^F#%F)Lr0=@Ej4uX;Nu~lS(sM z+W;vgO(GHuNz?pMk1^&A&$J{S&qRO+6UIF@fPl|;=Yx1KhM^b=KM6g6Y8*p6J>iFV z8^a*O-og+R_Q_kAC-NVAC?C{?&PWJ?0(9b| e#12u#6M&|Ofpcm~N>YXlQ2~lE+3cW2V&*^NNQRdH literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Images.xcassets/Premium/StickerIcon.imageset/addreactions_32.pdf b/submodules/TelegramUI/Images.xcassets/Premium/StickerIcon.imageset/addreactions_32.pdf deleted file mode 100644 index f469aa5214..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Premium/StickerIcon.imageset/addreactions_32.pdf +++ /dev/null @@ -1,201 +0,0 @@ -%PDF-1.7 - -1 0 obj - << /Length 2 0 R - /Range [ 0.000000 1.000000 0.000000 1.000000 0.000000 1.000000 ] - /Domain [ 0.000000 1.000000 ] - /FunctionType 4 - >> -stream -{ 0.000000 exch 0.721569 exch 1.000000 exch dup 0.000000 gt { exch pop exch pop exch pop dup 0.000000 sub 0.000000 mul 0.000000 add exch dup 0.000000 sub -0.243137 mul 0.721569 add exch dup 0.000000 sub 0.000000 mul 1.000000 add exch } if dup 1.000000 gt { exch pop exch pop exch pop 0.000000 exch 0.478431 exch 1.000000 exch } if pop } -endstream -endobj - -2 0 obj - 337 -endobj - -3 0 obj - << /Pattern << /P1 << /Matrix [ 0.000000 -32.000000 32.000000 0.000000 -32.000000 32.000000 ] - /Shading << /Coords [ 0.000000 0.000000 1.000000 0.000000 ] - /ColorSpace /DeviceRGB - /Function 1 0 R - /Domain [ 0.000000 1.000000 ] - /ShadingType 2 - /Extend [ true true ] - >> - /PatternType 2 - /Type /Pattern - >> >> >> -endobj - -4 0 obj - << /Length 5 0 R >> -stream -/DeviceRGB CS -/DeviceRGB cs -q -1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm -1.000000 1.000000 1.000000 scn -0.000000 16.000000 m -0.000000 24.836555 7.163444 32.000000 16.000000 32.000000 c -16.000000 32.000000 l -24.836555 32.000000 32.000000 24.836555 32.000000 16.000000 c -32.000000 16.000000 l -32.000000 7.163445 24.836555 0.000000 16.000000 0.000000 c -16.000000 0.000000 l -7.163444 0.000000 0.000000 7.163445 0.000000 16.000000 c -0.000000 16.000000 l -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm -/Pattern cs -/P1 scn -16.000000 0.000000 m -17.874004 0.000000 19.672758 0.322180 21.343897 0.914169 c -21.572962 0.677401 21.840872 0.478514 22.138031 0.327103 c -22.516409 0.134308 22.909628 0.062992 23.304974 0.030691 c -23.679550 0.000088 24.134321 0.000103 24.661480 0.000122 c -27.338524 0.000122 l -27.865683 0.000103 28.320454 0.000088 28.695030 0.030691 c -29.090376 0.062992 29.483595 0.134308 29.861973 0.327103 c -30.426460 0.614723 30.885403 1.073666 31.173021 1.638149 c -31.365814 2.016529 31.437132 2.409748 31.469433 2.805094 c -31.500034 3.179638 31.500019 3.634357 31.500002 4.161457 c -31.500002 4.161480 l -31.500002 4.161600 l -31.500002 4.838646 l -31.500002 4.838766 l -31.500002 4.838789 l -31.500019 5.365887 31.500034 5.820606 31.469433 6.195150 c -31.437132 6.590496 31.365814 6.983715 31.173021 7.362093 c -30.938610 7.822155 30.590397 8.212109 30.163998 8.496347 c -30.163998 8.551201 l -31.336399 10.775940 32.000000 13.310474 32.000000 16.000000 c -32.000000 24.836555 24.836555 32.000000 16.000000 32.000000 c -7.163444 32.000000 0.000000 24.836555 0.000000 16.000000 c -0.000000 7.163445 7.163444 0.000000 16.000000 0.000000 c -h -16.562183 8.757324 m -20.546453 6.359240 l -20.584953 6.699120 20.660887 7.036112 20.826982 7.362093 c -21.061394 7.822151 21.409601 8.212103 21.835997 8.496340 c -21.835997 9.500063 l -21.835997 10.039848 21.938705 10.555647 22.125647 11.028978 c -21.774387 12.530510 l -21.686312 12.907011 21.814457 13.301291 22.107056 13.554068 c -26.503191 17.351892 l -27.199739 17.953642 26.828377 19.096992 25.911175 19.174591 c -20.119438 19.664600 l -19.735479 19.697086 19.400976 19.939270 19.250256 20.293901 c -16.982876 25.628805 l -16.624168 26.472807 15.427922 26.472807 15.069214 25.628805 c -12.801836 20.293903 l -12.651114 19.939270 12.316612 19.697086 11.932652 19.664600 c -6.140916 19.174591 l -5.223714 19.096992 4.852351 17.953640 5.548900 17.351891 c -7.200050 15.925461 l -7.880803 15.337358 8.782333 15.071831 9.673182 15.197048 c -19.282505 16.547745 l -19.848860 16.627354 20.083559 15.847515 19.567341 15.601313 c -11.272570 11.645247 l -10.417443 11.237408 9.794044 10.463003 9.578240 9.540506 c -8.956986 6.884823 l -8.747575 5.989647 9.717782 5.283152 10.505456 5.757242 c -15.489906 8.757324 l -15.819762 8.955860 16.232327 8.955860 16.562183 8.757324 c -h -22.579525 1.224531 m -22.517185 1.256849 22.456810 1.292316 22.398592 1.330725 c -22.110716 1.520653 21.875710 1.782589 21.717987 2.092140 c -21.500000 2.519964 21.500000 3.080017 21.500000 4.200123 c -21.500000 4.800121 l -21.500000 5.187914 21.500002 5.508577 21.509048 5.779865 c -21.523994 6.228132 21.563643 6.541590 21.668795 6.800331 c -21.683817 6.837294 21.700174 6.873140 21.717989 6.908104 c -21.909735 7.284428 22.215696 7.590389 22.592020 7.782135 c -22.663559 7.818586 22.738798 7.848942 22.819733 7.874222 c -22.825129 7.875908 22.830549 7.877571 22.835997 7.879211 c -22.835997 7.992439 l -22.835995 9.500063 l -22.835995 11.247492 24.252565 12.664062 25.999994 12.664062 c -27.747423 12.664062 29.163994 11.247492 29.163994 9.500063 c -29.163994 7.879215 l -29.251150 7.852966 29.331669 7.821018 29.407982 7.782135 c -29.490490 7.740095 29.569614 7.692564 29.644896 7.640007 c -29.912977 7.452845 30.132307 7.201921 30.282015 6.908104 c -30.500002 6.480280 30.500002 5.920227 30.500002 4.800121 c -30.500002 4.200123 l -30.500002 3.080017 30.500002 2.519964 30.282015 2.092140 c -30.258047 2.045099 30.232294 1.999159 30.204842 1.954403 c -30.012678 1.641111 29.737267 1.385887 29.407982 1.218109 c -28.980160 1.000122 28.420107 1.000122 27.300003 1.000122 c -24.700001 1.000122 l -23.579897 1.000122 23.019844 1.000122 22.592020 1.218109 c -22.587847 1.220236 22.583681 1.222376 22.579525 1.224531 c -h -25.999994 11.336063 m -24.986000 11.336063 24.163994 10.514057 24.163994 9.500063 c -24.163994 7.998974 l -24.327213 8.000122 24.505131 8.000122 24.700001 8.000122 c -27.299999 8.000122 l -27.494865 8.000122 27.672779 8.000122 27.835995 7.998974 c -27.835995 9.500063 l -27.835995 10.514057 27.013988 11.336063 25.999994 11.336063 c -h -f* -n -Q - -endstream -endobj - -5 0 obj - 4545 -endobj - -6 0 obj - << /Annots [] - /Type /Page - /MediaBox [ 0.000000 0.000000 32.000000 32.000000 ] - /Resources 3 0 R - /Contents 4 0 R - /Parent 7 0 R - >> -endobj - -7 0 obj - << /Kids [ 6 0 R ] - /Count 1 - /Type /Pages - >> -endobj - -8 0 obj - << /Pages 7 0 R - /Type /Catalog - >> -endobj - -xref -0 9 -0000000000 65535 f -0000000010 00000 n -0000000531 00000 n -0000000553 00000 n -0000001179 00000 n -0000005780 00000 n -0000005803 00000 n -0000005976 00000 n -0000006050 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 8 0 R - /Size 9 ->> -startxref -6109 -%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 7b693575f3..debe3c700c 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -982,7 +982,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } var hasPremium = false - if case let .user(user) = peer, user.flags.contains(.isPremium) { + if case let .user(user) = peer, user.isPremium { hasPremium = true } @@ -1079,6 +1079,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts() let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, selectAll: selectAll)), items: .single(actions), recognizer: recognizer, gesture: gesture) + controller.getOverlayViews = { [weak self] in + guard let strongSelf = self else { + return [] + } + return [strongSelf.chatDisplayNode.navigateButtons.view] + } strongSelf.currentContextController = controller controller.reactionSelected = { [weak controller] value, isLarge in @@ -2347,15 +2353,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let message = message else { return } + let context = strongSelf.context let chatPresentationInterfaceState = strongSelf.presentationInterfaceState let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) - let isCopyLink: Bool + var isCopyLink = false + var isForward = false if message.id.namespace == Namespaces.Message.Cloud, let _ = message.peers[message.id.peerId] as? TelegramChannel, !(message.media.first is TelegramMediaAction) { isCopyLink = true - } else { - isCopyLink = false + } else if let forwardInfo = message.forwardInfo, let _ = forwardInfo.author as? TelegramChannel { + isCopyLink = true + isForward = true } actionSheet.setItemGroups([ActionSheetItemGroup(items: [ @@ -2368,13 +2377,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }), ActionSheetButtonItem(title: isCopyLink ? strongSelf.presentationData.strings.Conversation_ContextMenuCopyLink : strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() - if isCopyLink, let channel = message.peers[message.id.peerId] as? TelegramChannel { + + var messageId = message.id + var channel = message.peers[message.id.peerId] + if isForward, let forwardMessageId = message.forwardInfo?.sourceMessageId, let forwardAuthor = message.forwardInfo?.author as? TelegramChannel { + messageId = forwardMessageId + channel = forwardAuthor + } + + if isCopyLink, let channel = channel as? TelegramChannel { var threadMessageId: MessageId? if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation { threadMessageId = replyThreadMessage.messageId } - let _ = (context.engine.messages.exportMessageLink(peerId: message.id.peerId, messageId: message.id, isThread: threadMessageId != nil) + let _ = (context.engine.messages.exportMessageLink(peerId: messageId.peerId, messageId: messageId, isThread: threadMessageId != nil) |> map { result -> String? in return result } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 4ab8bc61e8..1ca0f117be 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -202,6 +202,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.isLoadingValue = isLoading if isLoading { self.historyNodeContainer.supernode?.insertSubnode(self.loadingNode, belowSubnode: self.historyNodeContainer) + self.loadingNode.isHidden = false self.loadingNode.layer.removeAllAnimations() self.loadingNode.alpha = 1.0 if animated { @@ -215,12 +216,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if let strongSelf = self { strongSelf.loadingNode.layer.removeAllAnimations() if completed { - strongSelf.loadingNode.removeFromSupernode() + strongSelf.loadingNode.isHidden = true } } }) } else { - self.loadingNode.removeFromSupernode() + self.loadingNode.isHidden = true } } } @@ -651,12 +652,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.emptyType = emptyType if let emptyType = emptyType, self.emptyNode == nil { let emptyNode = ChatEmptyNode(context: self.context, interaction: self.interfaceInteraction) - if let (size, insets) = self.validEmptyNodeLayout { - emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, size: size, insets: insets, transition: .immediate) - } emptyNode.isHidden = self.restrictedNode != nil self.emptyNode = emptyNode self.historyNodeContainer.supernode?.insertSubnode(emptyNode, aboveSubnode: self.historyNodeContainer) + if let (size, insets) = self.validEmptyNodeLayout { + emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, loadingNode: wasLoading && self.loadingNode.supernode != nil ? self.loadingNode : nil, size: size, insets: insets, transition: .immediate) + } if animated { emptyNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } @@ -1211,7 +1212,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { emptyNodeInsets.bottom += inputPanelsHeight self.validEmptyNodeLayout = (contentBounds.size, emptyNodeInsets) if let emptyNode = self.emptyNode, let emptyType = self.emptyType { - emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, size: contentBounds.size, insets: emptyNodeInsets, transition: transition) + emptyNode.updateLayout(interfaceState: self.chatPresentationInterfaceState, emptyType: emptyType, loadingNode: nil, size: contentBounds.size, insets: emptyNodeInsets, transition: transition) transition.updateFrame(node: emptyNode, frame: contentBounds) } diff --git a/submodules/TelegramUI/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Sources/ChatEmptyNode.swift index 0513c04797..5b87ffd1fe 100644 --- a/submodules/TelegramUI/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Sources/ChatEmptyNode.swift @@ -807,7 +807,25 @@ final class ChatEmptyNode: ASDisplayNode { self.addSubnode(self.backgroundNode) } - func updateLayout(interfaceState: ChatPresentationInterfaceState, emptyType: ChatHistoryNodeLoadState.EmptyType, size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) { + func animateFromLoadingNode(_ loadingNode: ChatLoadingNode) { + guard let (_, node) = content else { + return + } + + let duration: Double = 0.2 + node.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration) + node.layer.animateScale(from: 0.0, to: 1.0, duration: duration, timingFunction: CAMediaTimingFunctionName.easeInEaseOut.rawValue) + + let targetCornerRadius = self.backgroundNode.backgroundCornerRadius + let targetFrame = self.backgroundNode.frame + let initialFrame = loadingNode.convert(loadingNode.progressFrame, to: self) + + self.backgroundNode.layer.animateFrame(from: initialFrame, to: targetFrame, duration: duration) + self.backgroundNode.update(size: initialFrame.size, cornerRadius: initialFrame.size.width / 2.0, transition: .immediate) + self.backgroundNode.update(size: targetFrame.size, cornerRadius: targetCornerRadius, transition: .animated(duration: duration, curve: .easeInOut)) + } + + func updateLayout(interfaceState: ChatPresentationInterfaceState, emptyType: ChatHistoryNodeLoadState.EmptyType, loadingNode: ChatLoadingNode?, size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) { if self.currentTheme !== interfaceState.theme || self.currentStrings !== interfaceState.strings { self.currentTheme = interfaceState.theme self.currentStrings = interfaceState.strings @@ -904,5 +922,9 @@ final class ChatEmptyNode: ASDisplayNode { transition.updateFrame(node: self.backgroundNode, frame: contentFrame) self.backgroundNode.update(size: self.backgroundNode.bounds.size, cornerRadius: min(20.0, self.backgroundNode.bounds.height / 2.0), transition: transition) + + if let loadingNode = loadingNode { + self.animateFromLoadingNode(loadingNode) + } } } diff --git a/submodules/TelegramUI/Sources/ChatLoadingNode.swift b/submodules/TelegramUI/Sources/ChatLoadingNode.swift index b0d1782f70..6ee6604077 100644 --- a/submodules/TelegramUI/Sources/ChatLoadingNode.swift +++ b/submodules/TelegramUI/Sources/ChatLoadingNode.swift @@ -38,5 +38,9 @@ final class ChatLoadingNode: ASDisplayNode { let activitySize = self.activityIndicator.measure(size) transition.updateFrame(node: self.activityIndicator, frame: CGRect(origin: CGPoint(x: displayRect.minX + floor((displayRect.width - activitySize.width) / 2.0) + self.offset.x, y: displayRect.minY + floor((displayRect.height - activitySize.height) / 2.0) + self.offset.y), size: activitySize)) } + + var progressFrame: CGRect { + return self.backgroundNode.frame + } } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index 8c0c3014ba..e91bd7f347 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -1659,7 +1659,7 @@ final class ChatMediaInputNode: ChatInputNode { return strongSelf.context.account.postbox.transaction { transaction -> (Bool, Bool) in let isStarred = getIsStickerSaved(transaction: transaction, fileId: item.file.fileId) var hasPremium = false - if let peer = transaction.getPeer(accountPeerId) as? TelegramUser, peer.flags.contains(.isPremium) { + if let peer = transaction.getPeer(accountPeerId) as? TelegramUser, peer.isPremium { hasPremium = true } return (isStarred, hasPremium) diff --git a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift index 81f5c9d977..cbede1a041 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift @@ -320,7 +320,7 @@ final class ChatMediaInputStickerGridItemNode: GridItemNode { lockBackground = UIImageView() lockBackground.clipsToBounds = true lockBackground.isUserInteractionEnabled = false - lockBackground.image = UIImage(bundleImageName: "Premium/StickerIcon") + lockBackground.image = PresentationResourcesChat.chatInputMediaStickerGridPremiumIcon(item.theme) self.lockBackground = lockBackground self.view.addSubview(lockBackground) diff --git a/submodules/TelegramUI/Sources/ChatTitleView.swift b/submodules/TelegramUI/Sources/ChatTitleView.swift index 5da89d82b8..e50ec52e0d 100644 --- a/submodules/TelegramUI/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Sources/ChatTitleView.swift @@ -37,6 +37,14 @@ private enum ChatTitleIcon { case mute } +private enum ChatTitleCredibilityIcon { + case none + case fake + case scam + case verified + case premium +} + final class ChatTitleView: UIView, NavigationBarTitleView { private let account: Account @@ -59,8 +67,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { private var titleLeftIcon: ChatTitleIcon = .none private var titleRightIcon: ChatTitleIcon = .none - private var titleFakeIcon = false - private var titleScamIcon = false + private var titleCredibilityIcon: ChatTitleCredibilityIcon = .none //private var networkStatusNode: ChatTitleNetworkStatusNode? @@ -106,8 +113,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { var segments: [AnimatedCountLabelNode.Segment] = [] var titleLeftIcon: ChatTitleIcon = .none var titleRightIcon: ChatTitleIcon = .none - var titleScamIcon = false - var titleFakeIcon = false + var titleCredibilityIcon: ChatTitleCredibilityIcon = .none var isEnabled = true switch titleContent { case let .peer(peerView, _, isScheduledMessages): @@ -134,9 +140,13 @@ final class ChatTitleView: UIView, NavigationBarTitleView { } } if peer.isFake { - titleFakeIcon = true + titleCredibilityIcon = .fake } else if peer.isScam { - titleScamIcon = true + titleCredibilityIcon = .scam + } else if peer.isVerified { + titleCredibilityIcon = .verified + } else if peer.isPremium { + titleCredibilityIcon = .premium } } if peerView.peerId.namespace == Namespaces.Peer.SecretChat { @@ -243,15 +253,20 @@ final class ChatTitleView: UIView, NavigationBarTitleView { updated = true } - if titleFakeIcon != self.titleFakeIcon { - self.titleFakeIcon = titleFakeIcon - self.titleCredibilityIconNode.image = titleFakeIcon ? PresentationResourcesChatList.fakeIcon(titleTheme, strings: self.strings, type: .regular) : nil - updated = true - } - - if titleScamIcon != self.titleScamIcon { - self.titleScamIcon = titleScamIcon - self.titleCredibilityIconNode.image = titleScamIcon ? PresentationResourcesChatList.scamIcon(titleTheme, strings: self.strings, type: .regular) : nil + if titleCredibilityIcon != self.titleCredibilityIcon { + self.titleCredibilityIcon = titleCredibilityIcon + switch titleCredibilityIcon { + case .none: + self.titleCredibilityIconNode.image = nil + case .fake: + self.titleCredibilityIconNode.image = PresentationResourcesChatList.fakeIcon(titleTheme, strings: self.strings, type: .regular) + case .scam: + self.titleCredibilityIconNode.image = PresentationResourcesChatList.scamIcon(titleTheme, strings: self.strings, type: .regular) + case .verified: + self.titleCredibilityIconNode.image = PresentationResourcesChatList.verifiedIcon(titleTheme) + case .premium: + self.titleCredibilityIconNode.image = PresentationResourcesChatList.premiumIcon(titleTheme) + } updated = true } @@ -685,10 +700,14 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: -image.size.width - 3.0 - UIScreenPixel, y: 4.0), size: image.size) } if let image = self.titleCredibilityIconNode.image { - self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width - image.size.width - 1.0, y: 2.0), size: image.size) + var originY: CGFloat = 3.0 + if [.fake, .scam].contains(self.titleCredibilityIcon) { + originY = 2.0 + } + self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width - image.size.width, y: originY), size: image.size) } if let image = self.titleRightIconNode.image { - self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0, y: 6.0), size: image.size) + self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.width + 3.0 + UIScreenPixel, y: 6.0), size: image.size) } } else { let titleSize = self.titleNode.updateLayout(size: CGSize(width: floor(clearBounds.width / 2.0 - leftIconWidth - credibilityIconWidth - rightIconWidth - titleSideInset * 2.0), height: size.height), animated: transition.isAnimated) @@ -705,10 +724,14 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.titleLeftIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.minX, y: titleFrame.minY + 4.0), size: image.size) } if let image = self.titleCredibilityIconNode.image { - self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 6.0), size: image.size) + var originY: CGFloat = titleFrame.minY + 7.0 + if [.fake, .scam].contains(self.titleCredibilityIcon) { + originY = titleFrame.minY + 6.0 + } + self.titleCredibilityIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width, y: originY), size: image.size) } if let image = self.titleRightIconNode.image { - self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width - 1.0, y: titleFrame.minY + 6.0), size: image.size) + self.titleRightIconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX - image.size.width, y: titleFrame.minY + 6.0), size: image.size) } } diff --git a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift index 3c707d6839..ec7e6e3ecf 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenLabeledValueItem.swift @@ -86,6 +86,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { private let maskNode: ASImageNode private let labelNode: ImmediateTextNode private let textNode: ImmediateTextNode + private let measureTextNode: ImmediateTextNode private let bottomSeparatorNode: ASDisplayNode private let expandBackgroundNode: ASImageNode @@ -120,6 +121,10 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { self.textNode.displaysAsynchronously = false self.textNode.isUserInteractionEnabled = false + self.measureTextNode = ImmediateTextNode() + self.measureTextNode.displaysAsynchronously = false + self.measureTextNode.isUserInteractionEnabled = false + self.bottomSeparatorNode = ASDisplayNode() self.bottomSeparatorNode.isLayerBacked = true @@ -285,38 +290,6 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { self.labelNode.attributedText = NSAttributedString(string: item.label, font: Font.regular(14.0), textColor: presentationData.theme.list.itemPrimaryTextColor) - var text = item.text - let maxNumberOfLines: Int - switch item.textBehavior { - case .singleLine: - maxNumberOfLines = 1 - self.textNode.maximumNumberOfLines = maxNumberOfLines - self.textNode.cutout = nil - self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(17.0), textColor: textColorValue) - case let .multiLine(maxLines, enabledEntities): - if !self.isExpanded { - text = trimToLineCount(text, lineCount: 3) - } - - maxNumberOfLines = self.isExpanded ? maxLines : 3 - self.textNode.maximumNumberOfLines = maxNumberOfLines - if enabledEntities.isEmpty { - self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(17.0), textColor: textColorValue) - } else { - let fontSize: CGFloat = 17.0 - - let baseFont = Font.regular(fontSize) - let linkFont = baseFont - let boldFont = Font.medium(fontSize) - let italicFont = Font.italic(fontSize) - let boldItalicFont = Font.semiboldItalic(fontSize) - let titleFixedFont = Font.monospace(fontSize) - - let entities = generateTextEntities(text, enabledTypes: enabledEntities) - self.textNode.attributedText = stringWithAppliedEntities(text, entities: entities, baseColor: textColorValue, linkColor: presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont) - } - } - if let icon = item.icon { let iconImage: UIImage? switch icon { @@ -332,6 +305,55 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { } let additionalSideInset: CGFloat = !self.iconNode.isHidden ? 32.0 : 0.0 + + var text = item.text + let maxNumberOfLines: Int + switch item.textBehavior { + case .singleLine: + maxNumberOfLines = 1 + self.textNode.maximumNumberOfLines = maxNumberOfLines + self.textNode.cutout = nil + self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(17.0), textColor: textColorValue) + case let .multiLine(maxLines, enabledEntities): + let originalText = text + if !self.isExpanded { + text = trimToLineCount(text, lineCount: 3) + } + + func createAttributedText(_ text: String) -> NSAttributedString { + if enabledEntities.isEmpty { + return NSAttributedString(string: text, font: Font.regular(17.0), textColor: textColorValue) + } else { + let fontSize: CGFloat = 17.0 + + let baseFont = Font.regular(fontSize) + let linkFont = baseFont + let boldFont = Font.medium(fontSize) + let italicFont = Font.italic(fontSize) + let boldItalicFont = Font.semiboldItalic(fontSize) + let titleFixedFont = Font.monospace(fontSize) + + let entities = generateTextEntities(text, enabledTypes: enabledEntities) + return stringWithAppliedEntities(text, entities: entities, baseColor: textColorValue, linkColor: presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont) + } + } + + self.measureTextNode.maximumNumberOfLines = 0 + self.measureTextNode.attributedText = createAttributedText(originalText) + + let textLayout = self.measureTextNode.updateLayoutInfo(CGSize(width: width - sideInset * 2.0 - additionalSideInset, height: .greatestFiniteMagnitude)) + var collapsedNumberOfLines = 3 + if textLayout.numberOfLines == 4 { + collapsedNumberOfLines = 4 + } + + self.textNode.attributedText = createAttributedText(text) + + maxNumberOfLines = self.isExpanded ? maxLines : collapsedNumberOfLines + self.textNode.maximumNumberOfLines = maxNumberOfLines + } + + let labelSize = self.labelNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude)) let textLayout = self.textNode.updateLayoutInfo(CGSize(width: width - sideInset * 2.0 - additionalSideInset, height: .greatestFiniteMagnitude)) let textSize = textLayout.size diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index 85bb7d78a0..c905ebf4b8 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -2278,6 +2278,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { if themeUpdated || !initializedCredibilityIcon { let image: UIImage? + var expandedImage: UIImage? if let peer = peer { self.initializedCredibilityIcon = true if peer.isFake { @@ -2297,6 +2298,36 @@ final class PeerInfoHeaderNode: ASDisplayNode { } else { image = nil } + } else if peer.isPremium { + if let sourceImage = UIImage(bundleImageName: "Peer Info/PremiumIcon") { + image = generateImage(sourceImage.size, contextGenerator: { size, context in + if let cgImage = sourceImage.cgImage { + context.clear(CGRect(origin: CGPoint(), size: size)) + context.clip(to: CGRect(origin: .zero, size: size), mask: cgImage) + + let colorsArray: [CGColor] = [ + UIColor(rgb: 0x418eff).cgColor, + UIColor(rgb: 0x418eff).cgColor, + UIColor(rgb: 0xfc7ebd).cgColor, + UIColor(rgb: 0xfc7ebd).cgColor + ] + var locations: [CGFloat] = [0.0, 0.35, 0.65, 1.0] + let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)! + + context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: size.width, y: size.height), options: CGGradientDrawingOptions()) + } + }, opaque: false) + expandedImage = generateImage(sourceImage.size, contextGenerator: { size, context in + if let cgImage = sourceImage.cgImage { + context.clear(CGRect(origin: CGPoint(), size: size)) + context.clip(to: CGRect(origin: .zero, size: size), mask: cgImage) + context.setFillColor(UIColor(rgb: 0xffffff, alpha: 0.75).cgColor) + context.fill(CGRect(origin: CGPoint(), size: size)) + } + }, opaque: false) + } else { + image = nil + } } else { image = nil } @@ -2304,7 +2335,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { image = nil } self.titleCredibilityIconNode.image = image - self.titleExpandedCredibilityIconNode.image = image + self.titleExpandedCredibilityIconNode.image = expandedImage ?? image } self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0 @@ -2524,7 +2555,6 @@ final class PeerInfoHeaderNode: ASDisplayNode { if let image = self.titleCredibilityIconNode.image { transition.updateFrame(node: self.titleCredibilityIconNode, frame: CGRect(origin: CGPoint(x: titleSize.width + 4.0, y: floor((titleSize.height - image.size.height) / 2.0) + 1.0), size: image.size)) - transition.updateFrame(node: self.titleExpandedCredibilityIconNode, frame: CGRect(origin: CGPoint(x: titleExpandedSize.width + 4.0, y: floor((titleExpandedSize.height - image.size.height) / 2.0) + 1.0), size: image.size)) } diff --git a/submodules/TelegramUI/Sources/TelegramRootController.swift b/submodules/TelegramUI/Sources/TelegramRootController.swift index 78c73bde49..7d5c6ae3d4 100644 --- a/submodules/TelegramUI/Sources/TelegramRootController.swift +++ b/submodules/TelegramUI/Sources/TelegramRootController.swift @@ -16,6 +16,8 @@ import DatePickerNode import DebugSettingsUI import TabBarUI +import TelegramCallsUI + public final class TelegramRootController: NavigationController { private let context: AccountContext diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 6d54223212..2e22810d86 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -445,7 +445,7 @@ public final class WebAppController: ViewController, AttachmentContainable { self.handleSendData(data: eventData) } case "web_app_setup_main_button": - if let webView = self.webView, !webView.didTouchOnce { + if let webView = self.webView, !webView.didTouchOnce && controller.url == nil { self.delayedScriptMessage = message } else if let eventData = (body["eventData"] as? String)?.data(using: .utf8), let json = try? JSONSerialization.jsonObject(with: eventData, options: []) as? [String: Any] { if var isVisible = json["is_visible"] as? Bool {