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 titleNode: TextNode
private var credibilityIconNode: ASImageNode?
private let statusNode: TextNode
private let dateNode: TextNode
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 (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()))
@ -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)))
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()
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()
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
if offset <= navigationBarSearchContentHeight + 1.0 && !isFirstFilter {
let _ = (strongSelf.context.engine.peers.currentChatListFilters()
|> deliverOnMainQueue).start(next: { [weak self] filters in
guard let strongSelf = self else {
return
}
let targetTab: ChatListFilterTabEntryId
let firstFilter = filters.first ?? .allChats
switch firstFilter {
case .allChats:
targetTab = .all
case let .filter(id, _, _, _):
targetTab = .filter(id)
}
strongSelf.selectTab(id: targetTab)
})
let firstFilter = strongSelf.chatListDisplayNode.containerNode.availableFilters.first ?? .all
let targetTab: ChatListFilterTabEntryId
switch firstFilter {
case .all:
targetTab = .all
case let .filter(filter):
targetTab = .filter(filter.id)
}
strongSelf.selectTab(id: targetTab)
} else {
if let searchContentNode = strongSelf.searchContentNode {
searchContentNode.updateExpansionProgress(1.0, animated: true)
@ -1262,11 +1255,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
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 {
return
}
if disabled {
if isDisabled {
let context = strongSelf.context
var replaceImpl: ((ViewController) -> Void)?
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 {
return
}
@ -1319,24 +1312,37 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
guard let strongSelf = self else {
return
}
let _ = (strongSelf.context.engine.peers.currentChatListFilters()
|> deliverOnMainQueue).start(next: { presetList in
guard let strongSelf = self else {
return
if isDisabled {
let context = strongSelf.context
var replaceImpl: ((ViewController) -> Void)?
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
for filter in presetList {
if filter.id == id {
strongSelf.push(chatListFilterPresetController(context: strongSelf.context, currentPreset: filter, updated: { _ in }))
f(.dismissWithoutContent)
found = true
break
strongSelf.push(controller)
} else {
let _ = (strongSelf.context.engine.peers.currentChatListFilters()
|> deliverOnMainQueue).start(next: { presetList in
guard let strongSelf = self else {
return
}
}
if !found {
f(.default)
}
})
var found = false
for filter in presetList {
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
}
let _ = combineLatest(
queue: Queue.mainQueue(),
context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId),
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false),
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true)
),
strongSelf.context.engine.peers.currentChatListFilters()
).start(next: { result, presetList in
guard let strongSelf = self else {
return
if isDisabled {
let context = strongSelf.context
var replaceImpl: ((ViewController) -> Void)?
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
for filter in presetList {
if filter.id == id, case let .filter(_, _, _, data) = filter {
let (accountPeer, limits, premiumLimits) = result
let isPremium = accountPeer?.isPremium ?? false
let limit = limits.maxFolderChatsCount
let premiumLimit = premiumLimits.maxFolderChatsCount
if data.includePeers.peers.count >= premiumLimit {
let controller = PremiumLimitScreen(context: context, subject: .chatsPerFolder, count: Int32(data.includePeers.peers.count), action: {})
strongSelf.push(controller)
f(.dismissWithoutContent)
return
} else if data.includePeers.peers.count >= limit && !isPremium {
var replaceImpl: ((ViewController) -> Void)?
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
}
let _ = (strongSelf.context.engine.peers.currentChatListFilters()
|> deliverOnMainQueue).start(next: { filters in
guard let strongSelf = self else {
strongSelf.push(controller)
} else {
let _ = combineLatest(
queue: Queue.mainQueue(),
context.engine.data.get(
TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId),
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false),
TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true)
),
strongSelf.context.engine.peers.currentChatListFilters()
).start(next: { result, presetList in
guard let strongSelf = self else {
return
}
var found = false
for filter in presetList {
if filter.id == id, case let .filter(_, _, _, data) = filter {
let (accountPeer, limits, premiumLimits) = result
let isPremium = accountPeer?.isPremium ?? false
let limit = limits.maxFolderChatsCount
let premiumLimit = premiumLimits.maxFolderChatsCount
if data.includePeers.peers.count >= premiumLimit {
let controller = PremiumLimitScreen(context: context, subject: .chatsPerFolder, count: Int32(data.includePeers.peers.count), action: {})
strongSelf.push(controller)
f(.dismissWithoutContent)
return
} else if data.includePeers.peers.count >= limit && !isPremium {
var replaceImpl: ((ViewController) -> Void)?
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
}
strongSelf.push(chatListFilterAddChatsController(context: strongSelf.context, filter: filter, allFilters: filters, limit: limits.maxFolderChatsCount, premiumLimit: premiumLimits.maxFolderChatsCount, isPremium: isPremium))
f(.dismissWithoutContent)
})
found = true
break
let _ = (strongSelf.context.engine.peers.currentChatListFilters()
|> deliverOnMainQueue).start(next: { filters in
guard let strongSelf = self else {
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 {
f(.default)
}
})
if !found {
f(.default)
}
})
}
})
})))
@ -1472,11 +1491,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller)
})
}
self.tabContainerNode.contextGesture = { id, sourceNode, gesture in
tabContextGesture(id, sourceNode, gesture, false)
self.tabContainerNode.contextGesture = { id, sourceNode, gesture, isDisabled in
tabContextGesture(id, sourceNode, gesture, false, isDisabled)
}
self.chatListDisplayNode.inlineTabContainerNode.contextGesture = { id, sourceNode, gesture in
tabContextGesture(id, sourceNode, gesture, true)
self.chatListDisplayNode.inlineTabContainerNode.contextGesture = { id, sourceNode, gesture, isDisabled in
tabContextGesture(id, sourceNode, gesture, true, isDisabled)
}
if case .group = self.groupId {

View File

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

View File

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

View File

@ -290,6 +290,7 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
let highlightBackgroundNode: ASDisplayNode
let avatarNode: AvatarNode
let titleLabelNode: ImmediateTextNode
var credibilityIconNode: ASImageNode?
let separatorNode: ASDisplayNode
var reactionIconNode: ReactionImageNode?
let action: () -> Void
@ -368,6 +369,24 @@ public final class ReactionListContextMenuContent: ContextControllerItemsContent
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.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.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 {
maxTextWidth -= 32.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 {
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 titleNode: TextNode
private var credibilityIconNode: ASImageNode?
private var verificationIconNode: ASImageNode?
private let statusNode: TextNode
private var badgeBackgroundNode: ASImageNode?
private var badgeTextNode: TextNode?