mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
004ebd58ad
commit
681b5c9d3a
@ -492,6 +492,30 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func playCameraAnimation() {
|
||||||
|
let animationBackgroundNode = ASImageNode()
|
||||||
|
animationBackgroundNode.isUserInteractionEnabled = false
|
||||||
|
animationBackgroundNode.frame = self.imageNode.frame
|
||||||
|
animationBackgroundNode.image = generateGradientFilledCircleImage(diameter: self.imageNode.frame.width, colors: AvatarNode.repostColors.map { $0.cgColor } as NSArray)
|
||||||
|
self.addSubnode(animationBackgroundNode)
|
||||||
|
|
||||||
|
let animationNode = AnimationNode(animation: "anim_camera", colors: [:], scale: 0.082)
|
||||||
|
animationNode.isUserInteractionEnabled = false
|
||||||
|
self.addSubnode(animationNode)
|
||||||
|
|
||||||
|
if var size = animationNode.preferredSize() {
|
||||||
|
size = CGSize(width: ceil(size.width), height: ceil(size.height))
|
||||||
|
animationNode.frame = CGRect(x: floor((self.bounds.width - size.width) / 2.0) + 1.0, y: floor((self.bounds.height - size.height) / 2.0), width: size.width, height: size.height)
|
||||||
|
Queue.mainQueue().after(0.15, {
|
||||||
|
animationNode.play()
|
||||||
|
animationNode.completion = { [weak animationNode, weak animationBackgroundNode] in
|
||||||
|
animationNode?.removeFromSupernode()
|
||||||
|
animationBackgroundNode?.removeFromSupernode()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public func setPeer(
|
public func setPeer(
|
||||||
accountPeerId: EnginePeer.Id,
|
accountPeerId: EnginePeer.Id,
|
||||||
postbox: Postbox,
|
postbox: Postbox,
|
||||||
@ -1151,6 +1175,10 @@ public final class AvatarNode: ASDisplayNode {
|
|||||||
self.contentNode.playRepostAnimation()
|
self.contentNode.playRepostAnimation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func playCameraAnimation() {
|
||||||
|
self.contentNode.playCameraAnimation ()
|
||||||
|
}
|
||||||
|
|
||||||
public func setPeer(
|
public func setPeer(
|
||||||
accountPeerId: EnginePeer.Id,
|
accountPeerId: EnginePeer.Id,
|
||||||
postbox: Postbox,
|
postbox: Postbox,
|
||||||
|
@ -163,6 +163,7 @@ public final class BrowserBookmarksScreen: ViewController {
|
|||||||
}, playMessageEffect: { _ in
|
}, playMessageEffect: { _ in
|
||||||
}, editMessageFactCheck: { _ in
|
}, editMessageFactCheck: { _ in
|
||||||
}, sendGift: { _ in
|
}, sendGift: { _ in
|
||||||
|
}, openUniqueGift: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
|
@ -137,10 +137,6 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
|||||||
self.zPosition = 1.0
|
self.zPosition = 1.0
|
||||||
}
|
}
|
||||||
|
|
||||||
override func didLoad() {
|
|
||||||
super.didLoad()
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc private func closePressed() {
|
@objc private func closePressed() {
|
||||||
guard let item = self.item else {
|
guard let item = self.item else {
|
||||||
return
|
return
|
||||||
@ -500,6 +496,14 @@ final class ChatListNoticeItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override public func selected() {
|
||||||
|
super.selected()
|
||||||
|
|
||||||
|
if case .setupPhoto = self.item?.notice {
|
||||||
|
self.avatarNode?.playCameraAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func okButtonPressed() {
|
@objc private func okButtonPressed() {
|
||||||
self.item?.action(.buttonChoice(isPositive: true))
|
self.item?.action(.buttonChoice(isPositive: true))
|
||||||
}
|
}
|
||||||
|
@ -791,6 +791,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||||
|
|
||||||
var credibilityIcon: EmojiStatusComponent.Content?
|
var credibilityIcon: EmojiStatusComponent.Content?
|
||||||
|
var credibilityParticleColor: UIColor?
|
||||||
var verifiedIcon: EmojiStatusComponent.Content?
|
var verifiedIcon: EmojiStatusComponent.Content?
|
||||||
switch item.peer {
|
switch item.peer {
|
||||||
case let .peer(peer, _):
|
case let .peer(peer, _):
|
||||||
@ -801,6 +802,9 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
credibilityIcon = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
credibilityIcon = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
||||||
} else if let emojiStatus = peer.emojiStatus {
|
} else if let emojiStatus = peer.emojiStatus {
|
||||||
credibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
credibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||||
|
if let color = emojiStatus.color {
|
||||||
|
credibilityParticleColor = UIColor(rgb: UInt32(bitPattern: color))
|
||||||
|
}
|
||||||
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
|
||||||
credibilityIcon = .premium(color: item.presentationData.theme.list.itemAccentColor)
|
credibilityIcon = .premium(color: item.presentationData.theme.list.itemAccentColor)
|
||||||
}
|
}
|
||||||
@ -1498,6 +1502,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
animationCache: animationCache,
|
animationCache: animationCache,
|
||||||
animationRenderer: animationRenderer,
|
animationRenderer: animationRenderer,
|
||||||
content: credibilityIcon,
|
content: credibilityIcon,
|
||||||
|
particleColor: credibilityParticleColor,
|
||||||
isVisibleForAnimations: strongSelf.visibilityStatus,
|
isVisibleForAnimations: strongSelf.visibilityStatus,
|
||||||
action: nil,
|
action: nil,
|
||||||
emojiFileUpdated: nil
|
emojiFileUpdated: nil
|
||||||
|
@ -141,6 +141,7 @@ public final class ContextMenuActionItem {
|
|||||||
public let textIcon: (PresentationTheme) -> UIImage?
|
public let textIcon: (PresentationTheme) -> UIImage?
|
||||||
public let textLinkAction: () -> Void
|
public let textLinkAction: () -> Void
|
||||||
public let action: ((Action) -> Void)?
|
public let action: ((Action) -> Void)?
|
||||||
|
public let longPressAction: ((Action) -> Void)?
|
||||||
|
|
||||||
convenience public init(
|
convenience public init(
|
||||||
id: AnyHashable? = nil,
|
id: AnyHashable? = nil,
|
||||||
@ -160,7 +161,8 @@ public final class ContextMenuActionItem {
|
|||||||
iconAnimation: IconAnimation? = nil,
|
iconAnimation: IconAnimation? = nil,
|
||||||
textIcon: @escaping (PresentationTheme) -> UIImage? = { _ in return nil },
|
textIcon: @escaping (PresentationTheme) -> UIImage? = { _ in return nil },
|
||||||
textLinkAction: @escaping () -> Void = {},
|
textLinkAction: @escaping () -> Void = {},
|
||||||
action: ((ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void)?
|
action: ((ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void)?,
|
||||||
|
longPressAction: ((ContextControllerProtocol?, @escaping (ContextMenuActionResult) -> Void) -> Void)? = nil
|
||||||
) {
|
) {
|
||||||
self.init(
|
self.init(
|
||||||
id: id,
|
id: id,
|
||||||
@ -184,6 +186,11 @@ public final class ContextMenuActionItem {
|
|||||||
return { impl in
|
return { impl in
|
||||||
action(impl.controller, impl.dismissWithResult)
|
action(impl.controller, impl.dismissWithResult)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
longPressAction: longPressAction.flatMap { longPressAction in
|
||||||
|
return { impl in
|
||||||
|
longPressAction(impl.controller, impl.dismissWithResult)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -206,7 +213,8 @@ public final class ContextMenuActionItem {
|
|||||||
iconAnimation: IconAnimation? = nil,
|
iconAnimation: IconAnimation? = nil,
|
||||||
textIcon: @escaping (PresentationTheme) -> UIImage? = { _ in return nil },
|
textIcon: @escaping (PresentationTheme) -> UIImage? = { _ in return nil },
|
||||||
textLinkAction: @escaping () -> Void = {},
|
textLinkAction: @escaping () -> Void = {},
|
||||||
action: ((Action) -> Void)?
|
action: ((Action) -> Void)?,
|
||||||
|
longPressAction: ((Action) -> Void)? = nil
|
||||||
) {
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.text = text
|
self.text = text
|
||||||
@ -226,6 +234,7 @@ public final class ContextMenuActionItem {
|
|||||||
self.textIcon = textIcon
|
self.textIcon = textIcon
|
||||||
self.textLinkAction = textLinkAction
|
self.textLinkAction = textLinkAction
|
||||||
self.action = action
|
self.action = action
|
||||||
|
self.longPressAction = longPressAction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -922,6 +922,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
|||||||
|
|
||||||
var updatedLabelBadgeImage: UIImage?
|
var updatedLabelBadgeImage: UIImage?
|
||||||
var credibilityIcon: EmojiStatusComponent.Content?
|
var credibilityIcon: EmojiStatusComponent.Content?
|
||||||
|
var credibilityParticleColor: UIColor?
|
||||||
var verifiedIcon: EmojiStatusComponent.Content?
|
var verifiedIcon: EmojiStatusComponent.Content?
|
||||||
|
|
||||||
if case .threatSelfAsSaved = item.aliasHandling, item.peer.id == item.context.accountPeerId {
|
if case .threatSelfAsSaved = item.aliasHandling, item.peer.id == item.context.accountPeerId {
|
||||||
@ -932,6 +933,9 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
|||||||
credibilityIcon = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
credibilityIcon = .text(color: item.presentationData.theme.chat.message.incoming.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
||||||
} else if let emojiStatus = item.peer.emojiStatus {
|
} else if let emojiStatus = item.peer.emojiStatus {
|
||||||
credibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
credibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2))
|
||||||
|
if let color = emojiStatus.color {
|
||||||
|
credibilityParticleColor = UIColor(rgb: UInt32(bitPattern: color))
|
||||||
|
}
|
||||||
} else if item.peer.isPremium && !item.context.isPremiumDisabled {
|
} else if item.peer.isPremium && !item.context.isPremiumDisabled {
|
||||||
credibilityIcon = .premium(color: item.presentationData.theme.list.itemAccentColor)
|
credibilityIcon = .premium(color: item.presentationData.theme.list.itemAccentColor)
|
||||||
}
|
}
|
||||||
@ -1504,6 +1508,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
|||||||
animationCache: animationCache,
|
animationCache: animationCache,
|
||||||
animationRenderer: animationRenderer,
|
animationRenderer: animationRenderer,
|
||||||
content: credibilityIcon,
|
content: credibilityIcon,
|
||||||
|
particleColor: credibilityParticleColor,
|
||||||
isVisibleForAnimations: strongSelf.visibilityStatus,
|
isVisibleForAnimations: strongSelf.visibilityStatus,
|
||||||
action: nil,
|
action: nil,
|
||||||
emojiFileUpdated: nil
|
emojiFileUpdated: nil
|
||||||
|
@ -2100,7 +2100,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
bottomNodeMergeStatus = .Both
|
bottomNodeMergeStatus = .Both
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentCredibilityIcon: EmojiStatusComponent.Content?
|
var currentCredibilityIcon: (EmojiStatusComponent.Content, UIColor?)?
|
||||||
|
|
||||||
var initialDisplayHeader = true
|
var initialDisplayHeader = true
|
||||||
if hidesHeaders || item.message.adAttribute != nil {
|
if hidesHeaders || item.message.adAttribute != nil {
|
||||||
@ -2163,18 +2163,18 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
|
|
||||||
if case let .peer(peerId) = item.chatLocation, let authorPeerId = item.message.author?.id, authorPeerId == peerId {
|
if case let .peer(peerId) = item.chatLocation, let authorPeerId = item.message.author?.id, authorPeerId == peerId {
|
||||||
if effectiveAuthor is TelegramChannel, let emojiStatus = effectiveAuthor.emojiStatus {
|
if effectiveAuthor is TelegramChannel, let emojiStatus = effectiveAuthor.emojiStatus {
|
||||||
currentCredibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor, themeColor: color.withMultipliedAlpha(0.4), loopMode: .count(2))
|
currentCredibilityIcon = (.animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor, themeColor: color.withMultipliedAlpha(0.4), loopMode: .count(2)), nil)
|
||||||
}
|
}
|
||||||
} else if effectiveAuthor.isScam {
|
} else if effectiveAuthor.isScam {
|
||||||
currentCredibilityIcon = .text(color: incoming ? item.presentationData.theme.theme.chat.message.incoming.scamColor : item.presentationData.theme.theme.chat.message.outgoing.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased())
|
currentCredibilityIcon = (.text(color: incoming ? item.presentationData.theme.theme.chat.message.incoming.scamColor : item.presentationData.theme.theme.chat.message.outgoing.scamColor, string: item.presentationData.strings.Message_ScamAccount.uppercased()), nil)
|
||||||
} else if effectiveAuthor.isFake {
|
} else if effectiveAuthor.isFake {
|
||||||
currentCredibilityIcon = .text(color: incoming ? item.presentationData.theme.theme.chat.message.incoming.scamColor : item.presentationData.theme.theme.chat.message.outgoing.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased())
|
currentCredibilityIcon = (.text(color: incoming ? item.presentationData.theme.theme.chat.message.incoming.scamColor : item.presentationData.theme.theme.chat.message.outgoing.scamColor, string: item.presentationData.strings.Message_FakeAccount.uppercased()), nil)
|
||||||
} else if let emojiStatus = effectiveAuthor.emojiStatus {
|
} else if let emojiStatus = effectiveAuthor.emojiStatus {
|
||||||
currentCredibilityIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor, themeColor: color.withMultipliedAlpha(0.4), loopMode: .count(2))
|
currentCredibilityIcon = (.animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : item.presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor, themeColor: color.withMultipliedAlpha(0.4), loopMode: .count(2)), emojiStatus.color.flatMap { UIColor(rgb: UInt32(bitPattern: $0)) })
|
||||||
} else if effectiveAuthor.isVerified {
|
} else if effectiveAuthor.isVerified {
|
||||||
currentCredibilityIcon = .verified(fillColor: item.presentationData.theme.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
currentCredibilityIcon = (.verified(fillColor: item.presentationData.theme.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.theme.list.itemCheckColors.foregroundColor, sizeType: .compact), nil)
|
||||||
} else if effectiveAuthor.isPremium {
|
} else if effectiveAuthor.isPremium {
|
||||||
currentCredibilityIcon = .premium(color: color.withMultipliedAlpha(0.4))
|
currentCredibilityIcon = (.premium(color: color.withMultipliedAlpha(0.4)), nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let rawAuthorNameColor = authorNameColor {
|
if let rawAuthorNameColor = authorNameColor {
|
||||||
@ -2414,7 +2414,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
}
|
}
|
||||||
|
|
||||||
var credibilityIconWidth: CGFloat = 0.0
|
var credibilityIconWidth: CGFloat = 0.0
|
||||||
if let currentCredibilityIcon = currentCredibilityIcon {
|
if let (currentCredibilityIcon, _) = currentCredibilityIcon {
|
||||||
credibilityIconWidth += 4.0
|
credibilityIconWidth += 4.0
|
||||||
switch currentCredibilityIcon {
|
switch currentCredibilityIcon {
|
||||||
case let .text(_, string):
|
case let .text(_, string):
|
||||||
@ -3223,7 +3223,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
nameNodeOriginY: CGFloat,
|
nameNodeOriginY: CGFloat,
|
||||||
authorNameColor: UIColor?,
|
authorNameColor: UIColor?,
|
||||||
layoutConstants: ChatMessageItemLayoutConstants,
|
layoutConstants: ChatMessageItemLayoutConstants,
|
||||||
currentCredibilityIcon: EmojiStatusComponent.Content?,
|
currentCredibilityIcon: (EmojiStatusComponent.Content, UIColor?)?,
|
||||||
adminNodeSizeApply: (CGSize, () -> TextNode?),
|
adminNodeSizeApply: (CGSize, () -> TextNode?),
|
||||||
boostNodeSizeApply: (CGSize, () -> TextNode?),
|
boostNodeSizeApply: (CGSize, () -> TextNode?),
|
||||||
contentUpperRightCorner: CGPoint,
|
contentUpperRightCorner: CGPoint,
|
||||||
@ -3428,7 +3428,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
nameHighlightNode.image = generateFilledRoundedRectImage(size: CGSize(width: 8.0, height: 8.0), cornerRadius: 4.0, color: nameColor.withAlphaComponent(0.1))?.stretchableImage(withLeftCapWidth: 4, topCapHeight: 4)
|
nameHighlightNode.image = generateFilledRoundedRectImage(size: CGSize(width: 8.0, height: 8.0), cornerRadius: 4.0, color: nameColor.withAlphaComponent(0.1))?.stretchableImage(withLeftCapWidth: 4, topCapHeight: 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let currentCredibilityIcon = currentCredibilityIcon {
|
if let (currentCredibilityIcon, currentParticleColor) = currentCredibilityIcon {
|
||||||
let credibilityIconView: ComponentHostView<Empty>
|
let credibilityIconView: ComponentHostView<Empty>
|
||||||
if let current = strongSelf.credibilityIconView {
|
if let current = strongSelf.credibilityIconView {
|
||||||
credibilityIconView = current
|
credibilityIconView = current
|
||||||
@ -3448,6 +3448,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
animationCache: item.context.animationCache,
|
animationCache: item.context.animationCache,
|
||||||
animationRenderer: item.context.animationRenderer,
|
animationRenderer: item.context.animationRenderer,
|
||||||
content: currentCredibilityIcon,
|
content: currentCredibilityIcon,
|
||||||
|
particleColor: currentParticleColor,
|
||||||
isVisibleForAnimations: strongSelf.visibilityStatus,
|
isVisibleForAnimations: strongSelf.visibilityStatus,
|
||||||
action: nil
|
action: nil
|
||||||
)
|
)
|
||||||
@ -5767,6 +5768,9 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
|
|
||||||
@objc private func credibilityButtonPressed() {
|
@objc private func credibilityButtonPressed() {
|
||||||
if let item = self.item, let credibilityIconView = self.credibilityIconView, let iconContent = self.credibilityIconContent, let peer = item.message.author {
|
if let item = self.item, let credibilityIconView = self.credibilityIconView, let iconContent = self.credibilityIconContent, let peer = item.message.author {
|
||||||
|
if case let .starGift(_, _, _, slug, _, _, _, _, _) = peer.emojiStatus?.content {
|
||||||
|
item.controllerInteraction.openUniqueGift(slug)
|
||||||
|
} else {
|
||||||
var emojiFileId: Int64?
|
var emojiFileId: Int64?
|
||||||
switch iconContent {
|
switch iconContent {
|
||||||
case let .animation(content, _, _, _, _):
|
case let .animation(content, _, _, _, _):
|
||||||
@ -5779,6 +5783,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
item.controllerInteraction.openPremiumStatusInfo(peer.id, credibilityIconView, emojiFileId, peer.nameColor ?? .blue)
|
item.controllerInteraction.openPremiumStatusInfo(peer.id, credibilityIconView, emojiFileId, peer.nameColor ?? .blue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func boostButtonPressed() {
|
@objc private func boostButtonPressed() {
|
||||||
guard let item = self.item, let peer = item.message.author else {
|
guard let item = self.item, let peer = item.message.author else {
|
||||||
|
@ -632,8 +632,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
}, playMessageEffect: { _ in
|
}, playMessageEffect: { _ in
|
||||||
}, editMessageFactCheck: { _ in
|
}, editMessageFactCheck: { _ in
|
||||||
}, sendGift: { _ in
|
}, sendGift: { _ in
|
||||||
|
}, openUniqueGift: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
|
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
}, scrollToMessageId: { _ in
|
}, scrollToMessageId: { _ in
|
||||||
|
@ -489,6 +489,7 @@ public final class ChatSendGroupMediaMessageContextPreview: UIView, ChatSendMess
|
|||||||
}, playMessageEffect: { _ in
|
}, playMessageEffect: { _ in
|
||||||
}, editMessageFactCheck: { _ in
|
}, editMessageFactCheck: { _ in
|
||||||
}, sendGift: { _ in
|
}, sendGift: { _ in
|
||||||
|
}, openUniqueGift: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
|
@ -268,6 +268,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
|
|||||||
public let playMessageEffect: (Message) -> Void
|
public let playMessageEffect: (Message) -> Void
|
||||||
public let editMessageFactCheck: (MessageId) -> Void
|
public let editMessageFactCheck: (MessageId) -> Void
|
||||||
public let sendGift: (EnginePeer.Id) -> Void
|
public let sendGift: (EnginePeer.Id) -> Void
|
||||||
|
public let openUniqueGift: (String) -> Void
|
||||||
|
|
||||||
public let requestMessageUpdate: (MessageId, Bool) -> Void
|
public let requestMessageUpdate: (MessageId, Bool) -> Void
|
||||||
public let cancelInteractiveKeyboardGestures: () -> Void
|
public let cancelInteractiveKeyboardGestures: () -> Void
|
||||||
@ -402,6 +403,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
|
|||||||
playMessageEffect: @escaping (Message) -> Void,
|
playMessageEffect: @escaping (Message) -> Void,
|
||||||
editMessageFactCheck: @escaping (MessageId) -> Void,
|
editMessageFactCheck: @escaping (MessageId) -> Void,
|
||||||
sendGift: @escaping (EnginePeer.Id) -> Void,
|
sendGift: @escaping (EnginePeer.Id) -> Void,
|
||||||
|
openUniqueGift: @escaping (String) -> Void,
|
||||||
requestMessageUpdate: @escaping (MessageId, Bool) -> Void,
|
requestMessageUpdate: @escaping (MessageId, Bool) -> Void,
|
||||||
cancelInteractiveKeyboardGestures: @escaping () -> Void,
|
cancelInteractiveKeyboardGestures: @escaping () -> Void,
|
||||||
dismissTextInput: @escaping () -> Void,
|
dismissTextInput: @escaping () -> Void,
|
||||||
@ -515,6 +517,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
|
|||||||
self.playMessageEffect = playMessageEffect
|
self.playMessageEffect = playMessageEffect
|
||||||
self.editMessageFactCheck = editMessageFactCheck
|
self.editMessageFactCheck = editMessageFactCheck
|
||||||
self.sendGift = sendGift
|
self.sendGift = sendGift
|
||||||
|
self.openUniqueGift = openUniqueGift
|
||||||
|
|
||||||
self.requestMessageUpdate = requestMessageUpdate
|
self.requestMessageUpdate = requestMessageUpdate
|
||||||
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
||||||
|
@ -229,7 +229,7 @@ public func makeEditorImageComposition(context: CIContext, postbox: Postbox, inp
|
|||||||
} else if values.isAvatar {
|
} else if values.isAvatar {
|
||||||
maskImage = rectangleMaskImage(size: CGSize(width: 1080.0, height: 1080.0))
|
maskImage = rectangleMaskImage(size: CGSize(width: 1080.0, height: 1080.0))
|
||||||
} else if let outputDimensions {
|
} else if let outputDimensions {
|
||||||
maskImage = rectangleMaskImage(size: outputDimensions.aspectFitted(CGSize(width: 1080.0, height: 1080.0)))
|
maskImage = rectangleMaskImage(size: outputDimensions.aspectFitted(CGSize(width: 1080.0, height: 1920.0)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let drawing = values.drawing, let image = CIImage(image: drawing, options: [.colorSpace: colorSpace]) {
|
if let drawing = values.drawing, let image = CIImage(image: drawing, options: [.colorSpace: colorSpace]) {
|
||||||
@ -308,8 +308,7 @@ private func makeEditorImageFrameComposition(context: CIContext, inputImage: CII
|
|||||||
let scaledSize = CGSize(width: minSize, height: minSize)
|
let scaledSize = CGSize(width: minSize, height: minSize)
|
||||||
resultImage = resultImage.transformed(by: CGAffineTransform(translationX: -(dimensions.width - scaledSize.width) / 2.0, y: -(dimensions.height - scaledSize.height) / 2.0)).cropped(to: CGRect(origin: .zero, size: scaledSize))
|
resultImage = resultImage.transformed(by: CGAffineTransform(translationX: -(dimensions.width - scaledSize.width) / 2.0, y: -(dimensions.height - scaledSize.height) / 2.0)).cropped(to: CGRect(origin: .zero, size: scaledSize))
|
||||||
} else if values.isCover, let outputDimensions {
|
} else if values.isCover, let outputDimensions {
|
||||||
let minSize = min(dimensions.width, dimensions.height)
|
let scaledSize = outputDimensions.aspectFitted(dimensions)
|
||||||
let scaledSize = outputDimensions.aspectFitted(CGSize(width: minSize, height: minSize))
|
|
||||||
resultImage = resultImage.transformed(by: CGAffineTransform(translationX: -(dimensions.width - scaledSize.width) / 2.0, y: -(dimensions.height - scaledSize.height) / 2.0)).cropped(to: CGRect(origin: .zero, size: scaledSize))
|
resultImage = resultImage.transformed(by: CGAffineTransform(translationX: -(dimensions.width - scaledSize.width) / 2.0, y: -(dimensions.height - scaledSize.height) / 2.0)).cropped(to: CGRect(origin: .zero, size: scaledSize))
|
||||||
} else if values.isStory {
|
} else if values.isStory {
|
||||||
resultImage = resultImage.cropped(to: CGRect(origin: .zero, size: dimensions))
|
resultImage = resultImage.cropped(to: CGRect(origin: .zero, size: dimensions))
|
||||||
|
@ -3680,6 +3680,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}, playMessageEffect: { _ in
|
}, playMessageEffect: { _ in
|
||||||
}, editMessageFactCheck: { _ in
|
}, editMessageFactCheck: { _ in
|
||||||
}, sendGift: { _ in
|
}, sendGift: { _ in
|
||||||
|
}, openUniqueGift: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
@ -10970,20 +10971,30 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
giftsContext?.updateFilter(updatedFilter)
|
giftsContext?.updateFilter(updatedFilter)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let switchToFilter: (ProfileGiftsContext.Filters) -> Void = { [weak giftsContext] value in
|
||||||
|
giftsContext?.updateFilter(value)
|
||||||
|
}
|
||||||
|
|
||||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unlimited, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unlimited, icon: { theme in
|
||||||
return filter.contains(.unlimited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
return filter.contains(.unlimited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
toggleFilter(.unlimited)
|
toggleFilter(.unlimited)
|
||||||
|
}, longPressAction: { _, f in
|
||||||
|
switchToFilter(.unlimited)
|
||||||
})))
|
})))
|
||||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Limited, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Limited, icon: { theme in
|
||||||
return filter.contains(.limited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
return filter.contains(.limited) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
toggleFilter(.limited)
|
toggleFilter(.limited)
|
||||||
|
}, longPressAction: { _, f in
|
||||||
|
switchToFilter(.limited)
|
||||||
})))
|
})))
|
||||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unique, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Unique, icon: { theme in
|
||||||
return filter.contains(.unique) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
return filter.contains(.unique) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
toggleFilter(.unique)
|
toggleFilter(.unique)
|
||||||
|
}, longPressAction: { _, f in
|
||||||
|
switchToFilter(.unique)
|
||||||
})))
|
})))
|
||||||
|
|
||||||
if channel.hasPermission(.sendSomething) {
|
if channel.hasPermission(.sendSomething) {
|
||||||
@ -10993,11 +11004,15 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
return filter.contains(.displayed) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
return filter.contains(.displayed) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
toggleFilter(.displayed)
|
toggleFilter(.displayed)
|
||||||
|
}, longPressAction: { _, f in
|
||||||
|
switchToFilter(.displayed)
|
||||||
})))
|
})))
|
||||||
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Hidden, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: strings.PeerInfo_Gifts_Hidden, icon: { theme in
|
||||||
return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
return filter.contains(.hidden) ? generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor) : nil
|
||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
toggleFilter(.hidden)
|
toggleFilter(.hidden)
|
||||||
|
}, longPressAction: { _, f in
|
||||||
|
switchToFilter(.hidden)
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -835,6 +835,7 @@ public final class PeerListItemComponent: Component {
|
|||||||
let avatarFrame = CGRect(origin: CGPoint(x: avatarLeftInset, y: floorToScreenPixels((height - verticalInset * 2.0 - avatarSize) / 2.0)), size: CGSize(width: avatarSize, height: avatarSize))
|
let avatarFrame = CGRect(origin: CGPoint(x: avatarLeftInset, y: floorToScreenPixels((height - verticalInset * 2.0 - avatarSize) / 2.0)), size: CGSize(width: avatarSize, height: avatarSize))
|
||||||
|
|
||||||
var statusIcon: EmojiStatusComponent.Content?
|
var statusIcon: EmojiStatusComponent.Content?
|
||||||
|
var particleColor: UIColor?
|
||||||
if let peer = component.peer {
|
if let peer = component.peer {
|
||||||
if peer.isScam {
|
if peer.isScam {
|
||||||
statusIcon = .text(color: component.theme.chat.message.incoming.scamColor, string: component.strings.Message_ScamAccount.uppercased())
|
statusIcon = .text(color: component.theme.chat.message.incoming.scamColor, string: component.strings.Message_ScamAccount.uppercased())
|
||||||
@ -842,6 +843,9 @@ public final class PeerListItemComponent: Component {
|
|||||||
statusIcon = .text(color: component.theme.chat.message.incoming.scamColor, string: component.strings.Message_FakeAccount.uppercased())
|
statusIcon = .text(color: component.theme.chat.message.incoming.scamColor, string: component.strings.Message_FakeAccount.uppercased())
|
||||||
} else if let emojiStatus = peer.emojiStatus {
|
} else if let emojiStatus = peer.emojiStatus {
|
||||||
statusIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: component.theme.list.mediaPlaceholderColor, themeColor: component.theme.list.itemAccentColor, loopMode: .count(2))
|
statusIcon = .animation(content: .customEmoji(fileId: emojiStatus.fileId), size: CGSize(width: 20.0, height: 20.0), placeholderColor: component.theme.list.mediaPlaceholderColor, themeColor: component.theme.list.itemAccentColor, loopMode: .count(2))
|
||||||
|
if let color = emojiStatus.color {
|
||||||
|
particleColor = UIColor(rgb: UInt32(bitPattern: color))
|
||||||
|
}
|
||||||
} else if peer.isVerified {
|
} else if peer.isVerified {
|
||||||
statusIcon = .verified(fillColor: component.theme.list.itemCheckColors.fillColor, foregroundColor: component.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
statusIcon = .verified(fillColor: component.theme.list.itemCheckColors.fillColor, foregroundColor: component.theme.list.itemCheckColors.foregroundColor, sizeType: .compact)
|
||||||
} else if peer.isPremium {
|
} else if peer.isPremium {
|
||||||
@ -1086,6 +1090,7 @@ public final class PeerListItemComponent: Component {
|
|||||||
animationCache: animationCache,
|
animationCache: animationCache,
|
||||||
animationRenderer: animationRenderer,
|
animationRenderer: animationRenderer,
|
||||||
content: statusIcon,
|
content: statusIcon,
|
||||||
|
particleColor: particleColor,
|
||||||
isVisibleForAnimations: true,
|
isVisibleForAnimations: true,
|
||||||
action: nil,
|
action: nil,
|
||||||
emojiFileUpdated: nil
|
emojiFileUpdated: nil
|
||||||
|
File diff suppressed because one or more lines are too long
@ -4333,6 +4333,7 @@ extension ChatControllerImpl {
|
|||||||
guard let self, let peerId = self.chatLocation.peerId else {
|
guard let self, let peerId = self.chatLocation.peerId else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if peerId.namespace == Namespaces.Peer.CloudUser {
|
if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||||
self.presentAttachmentMenu(subject: .gift)
|
self.presentAttachmentMenu(subject: .gift)
|
||||||
Queue.mainQueue().after(0.5) {
|
Queue.mainQueue().after(0.5) {
|
||||||
|
@ -4585,6 +4585,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
let controller = self.context.sharedContext.makeGiftOptionsController(context: context, peerId: peerId, premiumOptions: premiumOptions, hasBirthday: hasBirthday, completion: nil)
|
let controller = self.context.sharedContext.makeGiftOptionsController(context: context, peerId: peerId, premiumOptions: premiumOptions, hasBirthday: hasBirthday, completion: nil)
|
||||||
self.push(controller)
|
self.push(controller)
|
||||||
})
|
})
|
||||||
|
}, openUniqueGift: { [weak self] slug in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.openUrl("https://t.me/nft/\(slug)", concealed: false)
|
||||||
}, requestMessageUpdate: { [weak self] id, scroll in
|
}, requestMessageUpdate: { [weak self] id, scroll in
|
||||||
if let self {
|
if let self {
|
||||||
self.chatDisplayNode.historyNode.requestMessageUpdate(id, andScrollToItem: scroll)
|
self.chatDisplayNode.historyNode.requestMessageUpdate(id, andScrollToItem: scroll)
|
||||||
|
@ -181,6 +181,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
|
|||||||
}, playMessageEffect: { _ in
|
}, playMessageEffect: { _ in
|
||||||
}, editMessageFactCheck: { _ in
|
}, editMessageFactCheck: { _ in
|
||||||
}, sendGift: { _ in
|
}, sendGift: { _ in
|
||||||
|
}, openUniqueGift: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
|
@ -1937,6 +1937,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}, playMessageEffect: { _ in
|
}, playMessageEffect: { _ in
|
||||||
}, editMessageFactCheck: { _ in
|
}, editMessageFactCheck: { _ in
|
||||||
}, sendGift: { _ in
|
}, sendGift: { _ in
|
||||||
|
}, openUniqueGift: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
@ -3256,15 +3257,18 @@ private func peerInfoControllerImpl(context: AccountContext, updatedPresentation
|
|||||||
} else if let _ = peer as? TelegramChannel {
|
} else if let _ = peer as? TelegramChannel {
|
||||||
var forumTopicThread: ChatReplyThreadMessage?
|
var forumTopicThread: ChatReplyThreadMessage?
|
||||||
var switchToRecommendedChannels = false
|
var switchToRecommendedChannels = false
|
||||||
|
var switchToGifts = false
|
||||||
switch mode {
|
switch mode {
|
||||||
case let .forumTopic(thread):
|
case let .forumTopic(thread):
|
||||||
forumTopicThread = thread
|
forumTopicThread = thread
|
||||||
case .recommendedChannels:
|
case .recommendedChannels:
|
||||||
switchToRecommendedChannels = true
|
switchToRecommendedChannels = true
|
||||||
|
case .gifts:
|
||||||
|
switchToGifts = true
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [], forumTopicThread: forumTopicThread, switchToRecommendedChannels: switchToRecommendedChannels)
|
return PeerInfoScreenImpl(context: context, updatedPresentationData: updatedPresentationData, peerId: peer.id, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, nearbyPeerDistance: nil, reactionSourceMessageId: nil, callMessages: [], forumTopicThread: forumTopicThread, switchToRecommendedChannels: switchToRecommendedChannels, switchToGifts: switchToGifts)
|
||||||
} else if peer is TelegramUser {
|
} else if peer is TelegramUser {
|
||||||
var nearbyPeerDistance: Int32?
|
var nearbyPeerDistance: Int32?
|
||||||
var reactionSourceMessageId: MessageId?
|
var reactionSourceMessageId: MessageId?
|
||||||
|
Loading…
x
Reference in New Issue
Block a user