Various fixes

This commit is contained in:
Ilya Laktyushin 2022-06-08 03:27:53 +04:00
parent c5b8b6392d
commit 59540c3571
6 changed files with 204 additions and 107 deletions

View File

@ -197,6 +197,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
private let avatarNode: AvatarNode private let avatarNode: AvatarNode
private let titleNode: TextNode private let titleNode: TextNode
private var credibilityIconNode: ASImageNode?
private let statusNode: TextNode private let statusNode: TextNode
private let dateNode: TextNode private let dateNode: TextNode
private let typeIconNode: ASImageNode private let typeIconNode: ASImageNode
@ -475,7 +476,26 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
let (dateLayout, dateApply) = makeDateLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: dateText, font: dateFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - rightInset), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (dateLayout, dateApply) = makeDateLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: dateText, font: dateFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - rightInset), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - dateRightInset - dateLayout.size.width - (item.editing ? -30.0 : 10.0)), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
var currentCredibilityIconImage: UIImage?
if let peer = item.topMessage.peers[item.topMessage.id.peerId], peer.id != item.context.account.peerId {
if peer.isScam {
currentCredibilityIconImage = PresentationResourcesChatList.scamIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
} else if peer.isFake {
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(item.presentationData.theme, strings: item.presentationData.strings, type: .regular)
} else if peer.isVerified {
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
} else if peer.isPremium && !premiumConfiguration.isPremiumDisabled {
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(item.presentationData.theme)
}
}
var additionalTitleInset: CGFloat = 0.0
if let currentCredibilityIconImage = currentCredibilityIconImage {
additionalTitleInset += 3.0 + currentCredibilityIconImage.size.width
}
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - additionalTitleInset - leftInset - dateRightInset - dateLayout.size.width - (item.editing ? -30.0 : 10.0)), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - dateRightInset - dateLayout.size.width - (item.editing ? -30.0 : 10.0)), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets())) let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - dateRightInset - dateLayout.size.width - (item.editing ? -30.0 : 10.0)), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
@ -614,11 +634,31 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
transition.updateFrameAdditive(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: floor((contentSize.height - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter))) transition.updateFrameAdditive(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: floor((contentSize.height - avatarDiameter) / 2.0)), size: CGSize(width: avatarDiameter, height: avatarDiameter)))
let _ = titleApply() let _ = titleApply()
transition.updateFrameAdditive(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: verticalInset), size: titleLayout.size)) let titleFrame = CGRect(origin: CGPoint(x: revealOffset + leftInset, y: verticalInset), size: titleLayout.size)
transition.updateFrameAdditive(node: strongSelf.titleNode, frame: titleFrame)
let _ = statusApply() let _ = statusApply()
transition.updateFrameAdditive(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: strongSelf.titleNode.frame.maxY + titleSpacing), size: statusLayout.size)) transition.updateFrameAdditive(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: strongSelf.titleNode.frame.maxY + titleSpacing), size: statusLayout.size))
if let currentCredibilityIconImage = currentCredibilityIconImage {
let iconNode: ASImageNode
if let current = strongSelf.credibilityIconNode {
iconNode = current
} else {
iconNode = ASImageNode()
iconNode.isLayerBacked = true
iconNode.displaysAsynchronously = false
iconNode.displayWithoutProcessing = true
strongSelf.containerNode.addSubnode(iconNode)
strongSelf.credibilityIconNode = iconNode
}
iconNode.image = currentCredibilityIconImage
transition.updateFrame(node: iconNode, frame: CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: floorToScreenPixels(titleFrame.midY - currentCredibilityIconImage.size.height / 2.0) - UIScreenPixel), size: currentCredibilityIconImage.size))
} else if let credibilityIconNode = strongSelf.credibilityIconNode {
strongSelf.credibilityIconNode = nil
credibilityIconNode.removeFromSupernode()
}
let _ = dateApply() let _ = dateApply()
transition.updateFrameAdditive(node: strongSelf.dateNode, frame: CGRect(origin: CGPoint(x: editingOffset + revealOffset + params.width - dateRightInset - dateLayout.size.width, y: floor((nodeLayout.contentSize.height - dateLayout.size.height) / 2.0) + 2.0), size: dateLayout.size)) transition.updateFrameAdditive(node: strongSelf.dateNode, frame: CGRect(origin: CGPoint(x: editingOffset + revealOffset + params.width - dateRightInset - dateLayout.size.width, y: floor((nodeLayout.contentSize.height - dateLayout.size.height) / 2.0) + 2.0), size: dateLayout.size))

View File

@ -267,22 +267,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let isFirstFilter = strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter == strongSelf.chatListDisplayNode.containerNode.availableFilters.first?.filter let isFirstFilter = strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter == strongSelf.chatListDisplayNode.containerNode.availableFilters.first?.filter
if offset <= navigationBarSearchContentHeight + 1.0 && !isFirstFilter { if offset <= navigationBarSearchContentHeight + 1.0 && !isFirstFilter {
let _ = (strongSelf.context.engine.peers.currentChatListFilters() let firstFilter = strongSelf.chatListDisplayNode.containerNode.availableFilters.first ?? .all
|> deliverOnMainQueue).start(next: { [weak self] filters in let targetTab: ChatListFilterTabEntryId
guard let strongSelf = self else { switch firstFilter {
return case .all:
} targetTab = .all
let targetTab: ChatListFilterTabEntryId case let .filter(filter):
let firstFilter = filters.first ?? .allChats targetTab = .filter(filter.id)
switch firstFilter { }
case .allChats: strongSelf.selectTab(id: targetTab)
targetTab = .all
case let .filter(id, _, _, _):
targetTab = .filter(id)
}
strongSelf.selectTab(id: targetTab)
})
} else { } else {
if let searchContentNode = strongSelf.searchContentNode { if let searchContentNode = strongSelf.searchContentNode {
searchContentNode.updateExpansionProgress(1.0, animated: true) searchContentNode.updateExpansionProgress(1.0, animated: true)
@ -1262,11 +1255,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.setToolbar(toolbar, transition: transition) strongSelf.setToolbar(toolbar, transition: transition)
})) }))
self.tabContainerNode.tabSelected = { [weak self] id, disabled in self.tabContainerNode.tabSelected = { [weak self] id, isDisabled in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
if disabled { if isDisabled {
let context = strongSelf.context let context = strongSelf.context
var replaceImpl: ((ViewController) -> Void)? var replaceImpl: ((ViewController) -> Void)?
let controller = PremiumLimitScreen(context: context, subject: .folders, count: strongSelf.tabContainerNode.filtersCount, action: { let controller = PremiumLimitScreen(context: context, subject: .folders, count: strongSelf.tabContainerNode.filtersCount, action: {
@ -1296,7 +1289,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
} }
let tabContextGesture: (Int32?, ContextExtractedContentContainingNode, ContextGesture, Bool) -> Void = { [weak self] id, sourceNode, gesture, keepInPlace in let tabContextGesture: (Int32?, ContextExtractedContentContainingNode, ContextGesture, Bool, Bool) -> Void = { [weak self] id, sourceNode, gesture, keepInPlace, isDisabled in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -1319,24 +1312,37 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
let _ = (strongSelf.context.engine.peers.currentChatListFilters() if isDisabled {
|> deliverOnMainQueue).start(next: { presetList in let context = strongSelf.context
guard let strongSelf = self else { var replaceImpl: ((ViewController) -> Void)?
return let controller = PremiumLimitScreen(context: context, subject: .folders, count: strongSelf.tabContainerNode.filtersCount, action: {
let controller = PremiumIntroScreen(context: context, source: .folders)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
} }
var found = false strongSelf.push(controller)
for filter in presetList { } else {
if filter.id == id { let _ = (strongSelf.context.engine.peers.currentChatListFilters()
strongSelf.push(chatListFilterPresetController(context: strongSelf.context, currentPreset: filter, updated: { _ in })) |> deliverOnMainQueue).start(next: { presetList in
f(.dismissWithoutContent) guard let strongSelf = self else {
found = true return
break
} }
} var found = false
if !found { for filter in presetList {
f(.default) if filter.id == id {
} strongSelf.push(chatListFilterPresetController(context: strongSelf.context, currentPreset: filter, updated: { _ in }))
}) f(.dismissWithoutContent)
found = true
break
}
}
if !found {
f(.default)
}
})
}
}) })
}))) })))
@ -1349,62 +1355,75 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
return return
} }
let _ = combineLatest( if isDisabled {
queue: Queue.mainQueue(), let context = strongSelf.context
context.engine.data.get( var replaceImpl: ((ViewController) -> Void)?
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId), let controller = PremiumLimitScreen(context: context, subject: .folders, count: strongSelf.tabContainerNode.filtersCount, action: {
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false), let controller = PremiumIntroScreen(context: context, source: .folders)
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true) replaceImpl?(controller)
), })
strongSelf.context.engine.peers.currentChatListFilters() replaceImpl = { [weak controller] c in
).start(next: { result, presetList in controller?.replace(with: c)
guard let strongSelf = self else {
return
} }
var found = false strongSelf.push(controller)
for filter in presetList { } else {
if filter.id == id, case let .filter(_, _, _, data) = filter { let _ = combineLatest(
let (accountPeer, limits, premiumLimits) = result queue: Queue.mainQueue(),
let isPremium = accountPeer?.isPremium ?? false context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId),
let limit = limits.maxFolderChatsCount TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false),
let premiumLimit = premiumLimits.maxFolderChatsCount TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true)
),
if data.includePeers.peers.count >= premiumLimit { strongSelf.context.engine.peers.currentChatListFilters()
let controller = PremiumLimitScreen(context: context, subject: .chatsPerFolder, count: Int32(data.includePeers.peers.count), action: {}) ).start(next: { result, presetList in
strongSelf.push(controller) guard let strongSelf = self else {
f(.dismissWithoutContent) return
return }
} else if data.includePeers.peers.count >= limit && !isPremium { var found = false
var replaceImpl: ((ViewController) -> Void)? for filter in presetList {
let controller = PremiumLimitScreen(context: context, subject: .chatsPerFolder, count: Int32(data.includePeers.peers.count), action: { if filter.id == id, case let .filter(_, _, _, data) = filter {
let controller = PremiumIntroScreen(context: context, source: .chatsPerFolder) let (accountPeer, limits, premiumLimits) = result
replaceImpl?(controller) let isPremium = accountPeer?.isPremium ?? false
})
replaceImpl = { [weak controller] c in let limit = limits.maxFolderChatsCount
controller?.replace(with: c) let premiumLimit = premiumLimits.maxFolderChatsCount
}
strongSelf.push(controller) if data.includePeers.peers.count >= premiumLimit {
f(.dismissWithoutContent) let controller = PremiumLimitScreen(context: context, subject: .chatsPerFolder, count: Int32(data.includePeers.peers.count), action: {})
return strongSelf.push(controller)
} f(.dismissWithoutContent)
return
let _ = (strongSelf.context.engine.peers.currentChatListFilters() } else if data.includePeers.peers.count >= limit && !isPremium {
|> deliverOnMainQueue).start(next: { filters in var replaceImpl: ((ViewController) -> Void)?
guard let strongSelf = self else { let controller = PremiumLimitScreen(context: context, subject: .chatsPerFolder, count: Int32(data.includePeers.peers.count), action: {
let controller = PremiumIntroScreen(context: context, source: .chatsPerFolder)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
strongSelf.push(controller)
f(.dismissWithoutContent)
return return
} }
strongSelf.push(chatListFilterAddChatsController(context: strongSelf.context, filter: filter, allFilters: filters, limit: limits.maxFolderChatsCount, premiumLimit: premiumLimits.maxFolderChatsCount, isPremium: isPremium))
f(.dismissWithoutContent) let _ = (strongSelf.context.engine.peers.currentChatListFilters()
}) |> deliverOnMainQueue).start(next: { filters in
found = true guard let strongSelf = self else {
break return
}
strongSelf.push(chatListFilterAddChatsController(context: strongSelf.context, filter: filter, allFilters: filters, limit: limits.maxFolderChatsCount, premiumLimit: premiumLimits.maxFolderChatsCount, isPremium: isPremium))
f(.dismissWithoutContent)
})
found = true
break
}
} }
} if !found {
if !found { f(.default)
f(.default) }
} })
}) }
}) })
}))) })))
@ -1472,11 +1491,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller) strongSelf.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller)
}) })
} }
self.tabContainerNode.contextGesture = { id, sourceNode, gesture in self.tabContainerNode.contextGesture = { id, sourceNode, gesture, isDisabled in
tabContextGesture(id, sourceNode, gesture, false) tabContextGesture(id, sourceNode, gesture, false, isDisabled)
} }
self.chatListDisplayNode.inlineTabContainerNode.contextGesture = { id, sourceNode, gesture in self.chatListDisplayNode.inlineTabContainerNode.contextGesture = { id, sourceNode, gesture, isDisabled in
tabContextGesture(id, sourceNode, gesture, true) tabContextGesture(id, sourceNode, gesture, true, isDisabled)
} }
if case .group = self.groupId { if case .group = self.groupId {

View File

@ -88,7 +88,7 @@ private final class ItemNode: ASDisplayNode {
private var theme: PresentationTheme? private var theme: PresentationTheme?
init(pressed: @escaping (Bool) -> Void, requestedDeletion: @escaping () -> Void, contextGesture: @escaping (ContextExtractedContentContainingNode, ContextGesture) -> Void) { init(pressed: @escaping (Bool) -> Void, requestedDeletion: @escaping () -> Void, contextGesture: @escaping (ContextExtractedContentContainingNode, ContextGesture, Bool) -> Void) {
self.pressed = pressed self.pressed = pressed
self.requestedDeletion = requestedDeletion self.requestedDeletion = requestedDeletion
@ -170,7 +170,7 @@ private final class ItemNode: ASDisplayNode {
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
contextGesture(strongSelf.extractedContainerNode, gesture) contextGesture(strongSelf.extractedContainerNode, gesture, strongSelf.isDisabled)
} }
self.extractedContainerNode.willUpdateIsExtractedToContextPreview = { [weak self] isExtracted, transition in self.extractedContainerNode.willUpdateIsExtractedToContextPreview = { [weak self] isExtracted, transition in
@ -467,7 +467,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
var tabSelected: ((ChatListFilterTabEntryId, Bool) -> Void)? var tabSelected: ((ChatListFilterTabEntryId, Bool) -> Void)?
var tabRequestedDeletion: ((ChatListFilterTabEntryId) -> Void)? var tabRequestedDeletion: ((ChatListFilterTabEntryId) -> Void)?
var addFilter: (() -> Void)? var addFilter: (() -> Void)?
var contextGesture: ((Int32?, ContextExtractedContentContainingNode, ContextGesture) -> Void)? var contextGesture: ((Int32?, ContextExtractedContentContainingNode, ContextGesture, Bool) -> Void)?
private var reorderingGesture: ReorderingGestureRecognizer? private var reorderingGesture: ReorderingGestureRecognizer?
private var reorderingItem: ChatListFilterTabEntryId? private var reorderingItem: ChatListFilterTabEntryId?
@ -739,7 +739,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
self?.tabSelected?(filter.id, disabled) self?.tabSelected?(filter.id, disabled)
}, requestedDeletion: { [weak self] in }, requestedDeletion: { [weak self] in
self?.tabRequestedDeletion?(filter.id) self?.tabRequestedDeletion?(filter.id)
}, contextGesture: { [weak self] sourceNode, gesture in }, contextGesture: { [weak self] sourceNode, gesture, isDisabled in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -748,9 +748,9 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
strongSelf.scrollNode.view.setContentOffset(strongSelf.scrollNode.view.contentOffset, animated: false) strongSelf.scrollNode.view.setContentOffset(strongSelf.scrollNode.view.contentOffset, animated: false)
switch filter { switch filter {
case let .filter(id, _, _): case let .filter(id, _, _):
strongSelf.contextGesture?(id, sourceNode, gesture) strongSelf.contextGesture?(id, sourceNode, gesture, isDisabled)
default: default:
strongSelf.contextGesture?(nil, sourceNode, gesture) strongSelf.contextGesture?(nil, sourceNode, gesture, isDisabled)
} }
}) })
self.itemNodes[filter.id] = itemNode self.itemNodes[filter.id] = itemNode

View File

@ -374,7 +374,7 @@ final class ChatListFilterTabInlineContainerNode: ASDisplayNode {
var tabSelected: ((ChatListFilterTabEntryId) -> Void)? var tabSelected: ((ChatListFilterTabEntryId) -> Void)?
var tabRequestedDeletion: ((ChatListFilterTabEntryId) -> Void)? var tabRequestedDeletion: ((ChatListFilterTabEntryId) -> Void)?
var addFilter: (() -> Void)? var addFilter: (() -> Void)?
var contextGesture: ((Int32?, ContextExtractedContentContainingNode, ContextGesture) -> Void)? var contextGesture: ((Int32?, ContextExtractedContentContainingNode, ContextGesture, Bool) -> Void)?
private var reorderingGesture: ReorderingGestureRecognizer? private var reorderingGesture: ReorderingGestureRecognizer?
private var reorderingItem: ChatListFilterTabEntryId? private var reorderingItem: ChatListFilterTabEntryId?
@ -653,9 +653,9 @@ final class ChatListFilterTabInlineContainerNode: ASDisplayNode {
strongSelf.scrollNode.view.setContentOffset(strongSelf.scrollNode.view.contentOffset, animated: false) strongSelf.scrollNode.view.setContentOffset(strongSelf.scrollNode.view.contentOffset, animated: false)
switch filter { switch filter {
case let .filter(id, _, _): case let .filter(id, _, _):
strongSelf.contextGesture?(id, sourceNode, gesture) strongSelf.contextGesture?(id, sourceNode, gesture, false)
default: default:
strongSelf.contextGesture?(nil, sourceNode, gesture) strongSelf.contextGesture?(nil, sourceNode, gesture, false)
} }
}), highlighted: ItemNode(pressed: { [weak self] in }), highlighted: ItemNode(pressed: { [weak self] in
self?.tabSelected?(filter.id) self?.tabSelected?(filter.id)
@ -670,9 +670,9 @@ final class ChatListFilterTabInlineContainerNode: ASDisplayNode {
strongSelf.scrollNode.view.panGestureRecognizer.isEnabled = false strongSelf.scrollNode.view.panGestureRecognizer.isEnabled = false
strongSelf.scrollNode.view.panGestureRecognizer.isEnabled = true strongSelf.scrollNode.view.panGestureRecognizer.isEnabled = true
strongSelf.scrollNode.view.setContentOffset(strongSelf.scrollNode.view.contentOffset, animated: false) strongSelf.scrollNode.view.setContentOffset(strongSelf.scrollNode.view.contentOffset, animated: false)
strongSelf.contextGesture?(id, sourceNode, gesture) strongSelf.contextGesture?(id, sourceNode, gesture, false)
default: default:
strongSelf.contextGesture?(nil, sourceNode, gesture) strongSelf.contextGesture?(nil, sourceNode, gesture, false)
} }
})) }))
self.itemNodePairs[filter.id] = itemNodePair self.itemNodePairs[filter.id] = itemNodePair

View File

@ -290,6 +290,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
let highlightBackgroundNode: ASDisplayNode let highlightBackgroundNode: ASDisplayNode
let avatarNode: AvatarNode let avatarNode: AvatarNode
let titleLabelNode: ImmediateTextNode let titleLabelNode: ImmediateTextNode
var credibilityIconNode: ASImageNode?
let separatorNode: ASDisplayNode let separatorNode: ASDisplayNode
var reactionIconNode: ReactionImageNode? var reactionIconNode: ReactionImageNode?
let action: () -> Void let action: () -> Void
@ -368,6 +369,24 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
self.accessibilityLabel = "\(item.peer.debugDisplayTitle) \(item.reaction ?? "")" self.accessibilityLabel = "\(item.peer.debugDisplayTitle) \(item.reaction ?? "")"
} }
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: self.context.currentAppConfiguration.with { $0 })
var currentCredibilityIconImage: UIImage?
if item.peer.id != self.context.account.peerId {
if item.peer.isScam {
currentCredibilityIconImage = PresentationResourcesChatList.scamIcon(presentationData.theme, strings: presentationData.strings, type: .regular)
} else if item.peer.isFake {
currentCredibilityIconImage = PresentationResourcesChatList.fakeIcon(presentationData.theme, strings: presentationData.strings, type: .regular)
} else if item.peer.isVerified {
currentCredibilityIconImage = PresentationResourcesChatList.verifiedIcon(presentationData.theme)
} else if item.peer.isPremium && !premiumConfiguration.isPremiumDisabled {
currentCredibilityIconImage = PresentationResourcesChatList.premiumIcon(presentationData.theme)
}
}
var additionalTitleInset: CGFloat = 0.0
if let currentCredibilityIconImage = currentCredibilityIconImage {
additionalTitleInset += 3.0 + currentCredibilityIconImage.size.width
}
self.highlightBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor self.highlightBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor
self.separatorNode.backgroundColor = presentationData.theme.contextMenu.itemSeparatorColor self.separatorNode.backgroundColor = presentationData.theme.contextMenu.itemSeparatorColor
@ -377,12 +396,32 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
self.avatarNode.setPeer(context: self.context, theme: presentationData.theme, peer: item.peer, synchronousLoad: true) self.avatarNode.setPeer(context: self.context, theme: presentationData.theme, peer: item.peer, synchronousLoad: true)
self.titleLabelNode.attributedText = NSAttributedString(string: item.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.regular(17.0), textColor: presentationData.theme.contextMenu.primaryColor) self.titleLabelNode.attributedText = NSAttributedString(string: item.peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder), font: Font.regular(17.0), textColor: presentationData.theme.contextMenu.primaryColor)
var maxTextWidth: CGFloat = size.width - avatarInset - avatarSize - avatarSpacing - sideInset var maxTextWidth: CGFloat = size.width - avatarInset - avatarSize - avatarSpacing - sideInset - additionalTitleInset
if reactionIconNode != nil { if reactionIconNode != nil {
maxTextWidth -= 32.0 maxTextWidth -= 32.0
} }
let titleSize = self.titleLabelNode.updateLayout(CGSize(width: maxTextWidth, height: 100.0)) let titleSize = self.titleLabelNode.updateLayout(CGSize(width: maxTextWidth, height: 100.0))
self.titleLabelNode.frame = CGRect(origin: CGPoint(x: avatarInset + avatarSize + avatarSpacing, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize) let titleFrame = CGRect(origin: CGPoint(x: avatarInset + avatarSize + avatarSpacing, y: floor((size.height - titleSize.height) / 2.0)), size: titleSize)
self.titleLabelNode.frame = titleFrame
if let currentCredibilityIconImage = currentCredibilityIconImage {
let iconNode: ASImageNode
if let current = self.credibilityIconNode {
iconNode = current
} else {
iconNode = ASImageNode()
iconNode.isLayerBacked = true
iconNode.displaysAsynchronously = false
iconNode.displayWithoutProcessing = true
self.addSubnode(iconNode)
self.credibilityIconNode = iconNode
}
iconNode.image = currentCredibilityIconImage
iconNode.frame = CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: floorToScreenPixels(titleFrame.midY - currentCredibilityIconImage.size.height / 2.0) + 1.0 - UIScreenPixel), size: currentCredibilityIconImage.size)
} else if let credibilityIconNode = self.credibilityIconNode {
self.credibilityIconNode = nil
credibilityIconNode.removeFromSupernode()
}
if let reactionIconNode = self.reactionIconNode { if let reactionIconNode = self.reactionIconNode {
let reactionSize = CGSize(width: 22.0, height: 22.0) let reactionSize = CGSize(width: 22.0, height: 22.0)

View File

@ -334,7 +334,6 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
private let avatarNode: AvatarNode private let avatarNode: AvatarNode
private let titleNode: TextNode private let titleNode: TextNode
private var credibilityIconNode: ASImageNode? private var credibilityIconNode: ASImageNode?
private var verificationIconNode: ASImageNode?
private let statusNode: TextNode private let statusNode: TextNode
private var badgeBackgroundNode: ASImageNode? private var badgeBackgroundNode: ASImageNode?
private var badgeTextNode: TextNode? private var badgeTextNode: TextNode?