Peer profile improvements

This commit is contained in:
Ilya Laktyushin 2021-11-09 22:22:31 +04:00
parent abfc1b54e5
commit 493fd5347d
22 changed files with 454 additions and 543 deletions

View File

@ -485,7 +485,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.tabContainerNode.cancelAnimations()
strongSelf.chatListDisplayNode.inlineTabContainerNode.cancelAnimations()
}
strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition)
strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition)
strongSelf.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition)
}
self.reloadFilters()
@ -549,7 +549,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
if let layout = self.validLayout {
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate)
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate)
self.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate)
}
@ -1414,7 +1414,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let navigationBarHeight = self.navigationBar?.frame.maxY ?? 0.0
transition.updateFrame(node: self.tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight - self.additionalNavigationBarHeight - 46.0 + tabContainerOffset), size: CGSize(width: layout.size.width, height: 46.0)))
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
if let tabContainerData = self.tabContainerData {
self.chatListDisplayNode.inlineTabContainerNode.isHidden = !tabContainerData.1 || tabContainerData.0.count <= 1
} else {
@ -1621,7 +1621,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.containerLayoutUpdated(layout, transition: transition)
(strongSelf.parent as? TabBarController)?.updateLayout(transition: transition)
} else {
strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: strongSelf.chatListDisplayNode.containerNode.transitionFraction, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring))
strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, transitionFraction: strongSelf.chatListDisplayNode.containerNode.transitionFraction, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring))
strongSelf.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: strongSelf.chatListDisplayNode.containerNode.transitionFraction, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring))
}
}

View File

@ -83,6 +83,7 @@ private final class ItemNode: ASDisplayNode {
private(set) var unreadCount: Int = 0
private var isReordering: Bool = false
private var isEditing: Bool = false
private var theme: PresentationTheme?
@ -192,6 +193,8 @@ private final class ItemNode: ASDisplayNode {
}
func updateText(strings: PresentationStrings, title: String, shortTitle: String, unreadCount: Int, unreadHasUnmuted: Bool, isNoFilter: Bool, selectionFraction: CGFloat, isEditing: Bool, isAllChats: Bool, isReordering: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) {
self.isEditing = isEditing
if self.theme !== presentationData.theme {
self.theme = presentationData.theme
@ -212,7 +215,7 @@ private final class ItemNode: ASDisplayNode {
self.selectionFraction = selectionFraction
self.unreadCount = unreadCount
transition.updateAlpha(node: self.containerNode, alpha: isReordering && isAllChats ? 0.5 : 1.0)
transition.updateAlpha(node: self.containerNode, alpha: isEditing || (isReordering && isAllChats) ? 0.5 : 1.0)
if isReordering && !isAllChats {
if self.deleteButtonNode == nil {
@ -234,7 +237,7 @@ private final class ItemNode: ASDisplayNode {
})
}
transition.updateAlpha(node: self.badgeContainerNode, alpha: (isReordering || unreadCount == 0) ? 0.0 : 1.0)
transition.updateAlpha(node: self.badgeContainerNode, alpha: (isEditing || isReordering || unreadCount == 0) ? 0.0 : 1.0)
let selectionAlpha: CGFloat = selectionFraction * selectionFraction
let deselectionAlpha: CGFloat = 1.0// - selectionFraction
@ -302,7 +305,7 @@ private final class ItemNode: ASDisplayNode {
self.badgeTextNode.frame = CGRect(origin: CGPoint(x: floorToScreenPixels((badgeBackgroundFrame.width - badgeSize.width) / 2.0), y: floor((badgeBackgroundFrame.height - badgeSize.height) / 2.0)), size: badgeSize)
let width: CGFloat
if self.unreadCount == 0 || self.isReordering {
if self.unreadCount == 0 || self.isReordering || self.isEditing {
if !self.isReordering {
self.badgeContainerNode.alpha = 0.0
}
@ -636,6 +639,11 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
let isFirstTime = self.currentParams == nil
let transition: ContainedViewLayoutTransition = isFirstTime ? .immediate : proposedTransition
var isEditing = isEditing
if isReordering {
isEditing = false
}
var focusOnSelectedFilter = self.currentParams?.selectedFilter != selectedFilter
let previousScrollBounds = self.scrollNode.bounds
let previousContentWidth = self.scrollNode.view.contentSize.width
@ -674,7 +682,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
self.currentParams = (size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering, isEditing, transitionFraction, presentationData: presentationData)
self.reorderingGesture?.isEnabled = isEditing || isReordering
self.reorderingGesture?.isEnabled = isReordering
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size))
@ -754,7 +762,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
selectionFraction = 0.0
}
itemNode.updateText(strings: presentationData.strings, title: filter.title(strings: presentationData.strings), shortTitle: filter.shortTitle(strings: presentationData.strings), unreadCount: unreadCount, unreadHasUnmuted: unreadHasUnmuted, isNoFilter: isNoFilter, selectionFraction: selectionFraction, isEditing: false, isAllChats: isNoFilter, isReordering: isEditing || isReordering, presentationData: presentationData, transition: itemNodeTransition)
itemNode.updateText(strings: presentationData.strings, title: filter.title(strings: presentationData.strings), shortTitle: filter.shortTitle(strings: presentationData.strings), unreadCount: unreadCount, unreadHasUnmuted: unreadHasUnmuted, isNoFilter: isNoFilter, selectionFraction: selectionFraction, isEditing: isEditing, isAllChats: isNoFilter, isReordering: isReordering, presentationData: presentationData, transition: itemNodeTransition)
}
var removeKeys: [ChatListFilterTabEntryId] = []
for (id, _) in self.itemNodes {

View File

@ -162,7 +162,6 @@ public final class InviteLinkQRCodeController: ViewController {
private let backgroundNode: ASDisplayNode
private let contentBackgroundNode: ASDisplayNode
private let titleNode: ASTextNode
private let subtitleNode: ASTextNode
private let cancelButton: HighlightableButtonNode
private let textNode: ImmediateTextNode
@ -209,9 +208,6 @@ public final class InviteLinkQRCodeController: ViewController {
self.titleNode = ASTextNode()
self.titleNode.attributedText = NSAttributedString(string: self.presentationData.strings.InviteLink_QRCode_Title, font: Font.bold(17.0), textColor: textColor)
self.subtitleNode = ASTextNode()
self.subtitleNode.attributedText = NSAttributedString(string: self.presentationData.strings.InviteLink_QRCode_Title, font: Font.regular(13.0), textColor: secondaryTextColor)
self.cancelButton = HighlightableButtonNode()
self.cancelButton.setTitle(self.presentationData.strings.Common_Done, with: Font.bold(17.0), with: accentColor, for: .normal)
@ -254,10 +250,8 @@ public final class InviteLinkQRCodeController: ViewController {
self.contentContainerNode.addSubnode(self.qrImageNode)
self.contentContainerNode.addSubnode(self.qrIconNode)
self.contentContainerNode.addSubnode(self.qrButtonNode)
let textFont = Font.regular(13.0)
self.textNode.attributedText = NSAttributedString(string: isGroup ? self.presentationData.strings.InviteLink_QRCode_Info : self.presentationData.strings.InviteLink_QRCode_InfoChannel, font: textFont, textColor: secondaryTextColor)
self.textNode.attributedText = NSAttributedString(string: isGroup ? self.presentationData.strings.InviteLink_QRCode_Info : self.presentationData.strings.InviteLink_QRCode_InfoChannel, font: Font.regular(13.0), textColor: secondaryTextColor)
self.buttonNode.title = self.presentationData.strings.InviteLink_QRCode_Share
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
@ -304,6 +298,7 @@ public final class InviteLinkQRCodeController: ViewController {
self.contentBackgroundNode.backgroundColor = self.presentationData.theme.actionSheet.opaqueItemBackgroundColor
self.titleNode.attributedText = NSAttributedString(string: self.titleNode.attributedText?.string ?? "", font: Font.bold(17.0), textColor: self.presentationData.theme.actionSheet.primaryTextColor)
self.textNode.attributedText = NSAttributedString(string: self.textNode.attributedText?.string ?? "", font: Font.regular(13.0), textColor: self.presentationData.theme.actionSheet.secondaryTextColor)
if previousTheme !== presentationData.theme, let (layout, navigationBarHeight) = self.containerLayout {
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)

View File

@ -9,6 +9,7 @@ import PresentationDataUtils
public enum ItemListPeerActionItemHeight {
case generic
case compactPeerList
case peerList
}
@ -173,6 +174,10 @@ class ItemListPeerActionItemNode: ListViewItemNode {
verticalInset = 14.0
verticalOffset = 0.0
leftInset = 65.0 + params.leftInset
case .compactPeerList:
verticalInset = 14.0
verticalOffset = 0.0
leftInset = 59.0 + params.leftInset
}
let editingOffset: CGFloat = (item.editing ? 38.0 : 0.0)

View File

@ -10,6 +10,7 @@ enum PeerInfoScreenActionColor {
enum PeerInfoScreenActionAligmnent {
case natural
case center
case peerList
}
final class PeerInfoScreenActionItem: PeerInfoScreenItem {
@ -78,7 +79,7 @@ private final class PeerInfoScreenActionItemNode: PeerInfoScreenItemNode {
self.addSubnode(self.activateArea)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenActionItem else {
return 10.0
}
@ -88,7 +89,10 @@ private final class PeerInfoScreenActionItemNode: PeerInfoScreenItemNode {
self.selectionNode.pressed = item.action
let sideInset: CGFloat = 16.0 + safeInsets.left
let leftInset = (item.icon == nil ? sideInset : sideInset + 29.0 + 16.0)
var leftInset = (item.icon == nil ? sideInset : sideInset + 29.0 + 16.0)
if case .peerList = item.alignment {
leftInset += 5.0
}
let rightInset = sideInset
let separatorInset = item.icon == nil ? sideInset : leftInset - 1.0
let titleFont = Font.regular(presentationData.listsFontSize.itemListBaseFontSize)
@ -131,7 +135,7 @@ private final class PeerInfoScreenActionItemNode: PeerInfoScreenItemNode {
transition.updateFrame(node: self.textNode, frame: textFrame)
}
let hasCorners = safeInsets.left > 0.0 && (topItem == nil || bottomItem == nil)
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil

View File

@ -42,6 +42,7 @@ final class PeerInfoScreenAddressItem: PeerInfoScreenItem {
private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
private let selectionNode: PeerInfoScreenSelectableBackgroundNode
private let bottomSeparatorNode: ASDisplayNode
private let maskNode: ASImageNode
private var item: PeerInfoScreenAddressItem?
private var itemNode: ItemListAddressItemNode?
@ -53,6 +54,9 @@ private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
self.bottomSeparatorNode = ASDisplayNode()
self.bottomSeparatorNode.isLayerBacked = true
self.maskNode = ASImageNode()
self.maskNode.isUserInteractionEnabled = false
super.init()
bringToFrontForHighlightImpl = { [weak self] in
@ -61,9 +65,10 @@ private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
self.addSubnode(self.bottomSeparatorNode)
self.addSubnode(self.selectionNode)
self.addSubnode(self.maskNode)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenAddressItem else {
return 10.0
}
@ -108,6 +113,14 @@ private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
let height = itemNode.contentSize.height
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil
self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
self.maskNode.frame = CGRect(origin: CGPoint(x: safeInsets.left, y: 0.0), size: CGSize(width: width - safeInsets.left - safeInsets.right, height: height))
self.bottomSeparatorNode.isHidden = hasBottomCorners
transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(), size: itemNode.bounds.size))
let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel

View File

@ -52,7 +52,7 @@ private final class PeerInfoScreenCallListItemNode: PeerInfoScreenItemNode {
self.addSubnode(self.selectionNode)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenCallListItem else {
return 10.0
}

View File

@ -36,7 +36,7 @@ private final class PeerInfoScreenCommentItemNode: PeerInfoScreenItemNode {
self.addSubnode(self.activateArea)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenCommentItem else {
return 10.0
}

View File

@ -28,6 +28,7 @@ private final class PeerInfoScreenDisclosureEncryptionKeyItemNode: PeerInfoScree
private let keyNode: ASImageNode
private let arrowNode: ASImageNode
private let bottomSeparatorNode: ASDisplayNode
private let maskNode: ASImageNode
private var item: PeerInfoScreenDisclosureEncryptionKeyItem?
@ -53,6 +54,9 @@ private final class PeerInfoScreenDisclosureEncryptionKeyItemNode: PeerInfoScree
self.bottomSeparatorNode = ASDisplayNode()
self.bottomSeparatorNode.isLayerBacked = true
self.maskNode = ASImageNode()
self.maskNode.isUserInteractionEnabled = false
super.init()
bringToFrontForHighlightImpl = { [weak self] in
@ -64,9 +68,10 @@ private final class PeerInfoScreenDisclosureEncryptionKeyItemNode: PeerInfoScree
self.addSubnode(self.textNode)
self.addSubnode(self.keyNode)
self.addSubnode(self.arrowNode)
self.addSubnode(self.maskNode)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenDisclosureEncryptionKeyItem else {
return 10.0
}
@ -106,6 +111,14 @@ private final class PeerInfoScreenDisclosureEncryptionKeyItemNode: PeerInfoScree
transition.updateFrame(node: self.textNode, frame: textFrame)
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil
self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
self.maskNode.frame = CGRect(origin: CGPoint(x: safeInsets.left, y: 0.0), size: CGSize(width: width - safeInsets.left - safeInsets.right, height: height))
self.bottomSeparatorNode.isHidden = hasBottomCorners
let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel
self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition)
transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset)))

View File

@ -109,7 +109,7 @@ private final class PeerInfoScreenDisclosureItemNode: PeerInfoScreenItemNode {
self.addSubnode(self.activateArea)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenDisclosureItem else {
return 10.0
}
@ -196,7 +196,7 @@ private final class PeerInfoScreenDisclosureItemNode: PeerInfoScreenItemNode {
transition.updateFrame(node: self.labelNode, frame: labelFrame)
transition.updateFrame(node: self.textNode, frame: textFrame)
let hasCorners = safeInsets.left > 0.0 && (topItem == nil || bottomItem == nil)
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil

View File

@ -36,7 +36,7 @@ private final class PeerInfoScreenHeaderItemNode: PeerInfoScreenItemNode {
self.addSubnode(self.activateArea)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenHeaderItem else {
return 10.0
}

View File

@ -52,7 +52,7 @@ private final class PeerInfoScreenInfoItemNode: PeerInfoScreenItemNode {
self.addSubnode(self.bottomSeparatorNode)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenInfoItem else {
return 10.0
}
@ -103,7 +103,7 @@ private final class PeerInfoScreenInfoItemNode: PeerInfoScreenItemNode {
separatorInset += 49.0
}
let hasCorners = safeInsets.left > 0.0 && (topItem == nil || bottomItem == nil)
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil

View File

@ -54,6 +54,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
private let selectionNode: PeerInfoScreenSelectableBackgroundNode
private let maskNode: ASImageNode
private let labelNode: ImmediateTextNode
private let textNode: ImmediateTextNode
private let bottomSeparatorNode: ASDisplayNode
@ -75,6 +76,9 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() })
self.selectionNode.isUserInteractionEnabled = false
self.maskNode = ASImageNode()
self.maskNode.isUserInteractionEnabled = false
self.labelNode = ImmediateTextNode()
self.labelNode.displaysAsynchronously = false
self.labelNode.isUserInteractionEnabled = false
@ -102,6 +106,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
self.addSubnode(self.bottomSeparatorNode)
self.addSubnode(self.selectionNode)
self.addSubnode(self.maskNode)
self.addSubnode(self.labelNode)
self.addSubnode(self.textNode)
@ -184,7 +189,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
}
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenLabeledValueItem else {
return 10.0
}
@ -267,6 +272,13 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: sideInset, y: height - UIScreenPixel), size: CGSize(width: width - sideInset, height: UIScreenPixel)))
transition.updateAlpha(node: self.bottomSeparatorNode, alpha: bottomItem == nil ? 0.0 : 1.0)
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil
self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
self.maskNode.frame = CGRect(origin: CGPoint(x: safeInsets.left, y: 0.0), size: CGSize(width: width - safeInsets.left - safeInsets.right, height: height))
self.bottomSeparatorNode.isHidden = hasBottomCorners
self.activateArea.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: height))
self.activateArea.accessibilityLabel = item.label

View File

@ -112,7 +112,7 @@ private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode {
}
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenMemberItem else {
return 10.0
}
@ -226,7 +226,7 @@ private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode {
transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(), size: itemNode.bounds.size))
let hasCorners = safeInsets.left > 0.0 && (topItem == nil || bottomItem == nil)
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil

View File

@ -84,7 +84,7 @@ private final class PeerInfoScreenSwitchItemNode: PeerInfoScreenItemNode {
}
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenSwitchItem else {
return 10.0
}
@ -149,7 +149,7 @@ private final class PeerInfoScreenSwitchItemNode: PeerInfoScreenItemNode {
}
}
let hasCorners = safeInsets.left > 0.0 && (topItem == nil || bottomItem == nil)
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil

View File

@ -9,6 +9,7 @@ import ContextUI
import PhotoResources
import TelegramUIPreferences
import ItemListPeerItem
import ItemListPeerActionItem
import MergeLists
import ItemListUI
@ -26,74 +27,117 @@ enum PeerMembersListAction {
case remove
}
private struct PeerMembersListEntry: Comparable, Identifiable {
let theme: PresentationTheme
let index: Int
let member: PeerInfoMember
var stableId: PeerId {
return self.member.id
private enum PeerMembersListEntryStableId: Hashable {
case addMember
case peer(PeerId)
}
private enum PeerMembersListEntry: Comparable, Identifiable {
case addMember(PresentationTheme, String)
case member(PresentationTheme, Int, PeerInfoMember)
var stableId: PeerMembersListEntryStableId {
switch self {
case .addMember:
return .addMember
case let .member(_, _, member):
return .peer(member.id)
}
}
static func ==(lhs: PeerMembersListEntry, rhs: PeerMembersListEntry) -> Bool {
return lhs.theme === rhs.theme && lhs.member == rhs.member
switch lhs {
case let .addMember(lhsTheme, lhsText):
if case let .addMember(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText {
return true
} else {
return false
}
case let .member(lhsTheme, lhsIndex, lhsMember):
if case let .member(rhsTheme, rhsIndex, rhsMember) = rhs, lhsTheme === rhsTheme, lhsIndex == rhsIndex, lhsMember == rhsMember {
return true
} else {
return false
}
}
}
static func <(lhs: PeerMembersListEntry, rhs: PeerMembersListEntry) -> Bool {
return lhs.index < rhs.index
switch lhs {
case .addMember:
switch rhs {
case .addMember:
return false
case .member:
return true
}
case let .member(_, lhsIndex, _):
switch rhs {
case .addMember:
return false
case let .member(_, rhsIndex, _):
return lhsIndex < rhsIndex
}
}
}
func item(context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) -> ListViewItem {
let member = self.member
let label: String?
if let rank = member.rank {
label = rank
} else {
switch member.role {
case .creator:
label = presentationData.strings.GroupInfo_LabelOwner
case .admin:
label = presentationData.strings.GroupInfo_LabelAdmin
case .member:
label = nil
}
func item(context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, addMemberAction: @escaping () -> Void, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) -> ListViewItem {
switch self {
case let .addMember(_, text):
return ItemListPeerActionItem(presentationData: ItemListPresentationData(presentationData), icon: PresentationResourcesItemList.addPersonIcon(presentationData.theme), title: text, alwaysPlain: true, sectionId: 0, height: .compactPeerList, color: .accent, editing: false, action: {
addMemberAction()
})
case let .member(_, _, member):
let label: String?
if let rank = member.rank {
label = rank
} else {
switch member.role {
case .creator:
label = presentationData.strings.GroupInfo_LabelOwner
case .admin:
label = presentationData.strings.GroupInfo_LabelAdmin
case .member:
label = nil
}
}
let actions = availableActionsForMemberOfPeer(accountPeerId: context.account.peerId, peer: enclosingPeer, member: member)
var options: [ItemListPeerItemRevealOption] = []
if actions.contains(.promote) && enclosingPeer is TelegramChannel{
options.append(ItemListPeerItemRevealOption(type: .neutral, title: presentationData.strings.GroupInfo_ActionPromote, action: {
action(member, .promote)
}))
}
if actions.contains(.restrict) {
if enclosingPeer is TelegramChannel {
options.append(ItemListPeerItemRevealOption(type: .warning, title: presentationData.strings.GroupInfo_ActionRestrict, action: {
action(member, .restrict)
}))
}
options.append(ItemListPeerItemRevealOption(type: .destructive, title: presentationData.strings.Common_Delete, action: {
action(member, .remove)
}))
}
return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: EnginePeer(member.peer), presence: member.presence.flatMap(EnginePeer.Presence.init), text: .presence, label: label == nil ? .none : .text(label!, .standard), editing: ItemListPeerItemEditing(editable: !options.isEmpty, editing: false, revealed: false), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, selectable: member.id != context.account.peerId, sectionId: 0, action: {
action(member, .open)
}, setPeerIdWithRevealedOptions: { _, _ in
}, removePeer: { _ in
}, contextAction: nil/*{ node, gesture in
openPeerContextAction(peer, node, gesture)
}*/, hasTopStripe: false, noInsets: true, disableInteractiveTransitionIfNecessary: true)
}
let actions = availableActionsForMemberOfPeer(accountPeerId: context.account.peerId, peer: enclosingPeer, member: member)
var options: [ItemListPeerItemRevealOption] = []
if actions.contains(.promote) && enclosingPeer is TelegramChannel{
options.append(ItemListPeerItemRevealOption(type: .neutral, title: presentationData.strings.GroupInfo_ActionPromote, action: {
action(member, .promote)
}))
}
if actions.contains(.restrict) {
if enclosingPeer is TelegramChannel {
options.append(ItemListPeerItemRevealOption(type: .warning, title: presentationData.strings.GroupInfo_ActionRestrict, action: {
action(member, .restrict)
}))
}
options.append(ItemListPeerItemRevealOption(type: .destructive, title: presentationData.strings.Common_Delete, action: {
action(member, .remove)
}))
}
return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, context: context, peer: EnginePeer(member.peer), presence: member.presence.flatMap(EnginePeer.Presence.init), text: .presence, label: label == nil ? .none : .text(label!, .standard), editing: ItemListPeerItemEditing(editable: !options.isEmpty, editing: false, revealed: false), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, selectable: member.id != context.account.peerId, sectionId: 0, action: {
action(member, .open)
}, setPeerIdWithRevealedOptions: { _, _ in
}, removePeer: { _ in
}, contextAction: nil/*{ node, gesture in
openPeerContextAction(peer, node, gesture)
}*/, hasTopStripe: false, noInsets: true, disableInteractiveTransitionIfNecessary: true)
}
}
private func preparedTransition(from fromEntries: [PeerMembersListEntry], to toEntries: [PeerMembersListEntry], context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) -> PeerMembersListTransaction {
private func preparedTransition(from fromEntries: [PeerMembersListEntry], to toEntries: [PeerMembersListEntry], context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, addMemberAction: @escaping () -> Void, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) -> PeerMembersListTransaction {
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enclosingPeer: enclosingPeer, action: action), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enclosingPeer: enclosingPeer, action: action), directionHint: nil) }
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enclosingPeer: enclosingPeer, addMemberAction: addMemberAction, action: action), directionHint: nil) }
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enclosingPeer: enclosingPeer, addMemberAction: addMemberAction, action: action), directionHint: nil) }
return PeerMembersListTransaction(deletions: deletions, insertions: insertions, updates: updates, animated: toEntries.count < fromEntries.count)
}
@ -101,6 +145,7 @@ private func preparedTransition(from fromEntries: [PeerMembersListEntry], to toE
final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
private let context: AccountContext
private let membersContext: PeerInfoMembersContext
private let addMemberAction: () -> Void
private let action: (PeerInfoMember, PeerMembersListAction) -> Void
weak var parentController: ViewController?
@ -132,9 +177,10 @@ final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
private var disposable: Disposable?
init(context: AccountContext, peerId: PeerId, membersContext: PeerInfoMembersContext, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) {
init(context: AccountContext, peerId: PeerId, membersContext: PeerInfoMembersContext, addMemberAction: @escaping () -> Void, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) {
self.context = context
self.membersContext = membersContext
self.addMemberAction = addMemberAction
self.action = action
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
@ -216,10 +262,16 @@ final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
private func updateState(enclosingPeer: Peer, state: PeerInfoMembersState, presentationData: PresentationData) {
var entries: [PeerMembersListEntry] = []
for member in state.members {
entries.append(PeerMembersListEntry(theme: presentationData.theme, index: entries.count, member: member))
if state.canAddMembers {
entries.append(.addMember(presentationData.theme, presentationData.strings.PeerInfo_ButtonAddMember))
}
let transaction = preparedTransition(from: self.currentEntries, to: entries, context: self.context, presentationData: presentationData, enclosingPeer: enclosingPeer, action: { [weak self] member, action in
for member in state.members {
entries.append(.member(presentationData.theme, entries.count, member))
}
let transaction = preparedTransition(from: self.currentEntries, to: entries, context: self.context, presentationData: presentationData, enclosingPeer: enclosingPeer, addMemberAction: { [weak self] in
self?.addMemberAction()
}, action: { [weak self] member, action in
self?.action(member, action)
})
self.enclosingPeer = enclosingPeer

View File

@ -1066,9 +1066,6 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
hasDiscussion = true
}
case .group:
if channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) {
result.append(.addMember)
}
if channel.flags.contains(.hasVoiceChat) {
hasVoiceChat = true
}
@ -1082,10 +1079,10 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
default:
displayLeave = false
}
result.append(.mute)
if hasVoiceChat || canStartVoiceChat {
result.append(.voiceChat)
}
result.append(.mute)
if hasDiscussion {
result.append(.discussion)
}
@ -1104,7 +1101,6 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
result.append(.more)
}
} else if let group = peer as? TelegramGroup {
var canAddMembers = false
var hasVoiceChat = false
var canStartVoiceChat = false
@ -1119,18 +1115,6 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
}
}
switch group.role {
case .admin, .creator:
canAddMembers = true
case .member:
break
}
if !group.hasBannedPermission(.banAddMembers) {
canAddMembers = true
}
if canAddMembers {
result.append(.addMember)
}
result.append(.mute)
if hasVoiceChat || canStartVoiceChat {
result.append(.voiceChat)

View File

@ -53,7 +53,7 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
private let action: (PeerInfoHeaderButtonNode, ContextGesture?) -> Void
let referenceNode: ContextReferenceContentNode
let containerNode: ContextControllerSourceNode
private let backgroundNode: ASImageNode
private let backgroundNode: ASDisplayNode
private let iconNode: ASImageNode
private let textNode: ImmediateTextNode
private var animationNode: AnimationNode?
@ -70,9 +70,8 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
self.containerNode = ContextControllerSourceNode()
self.containerNode.animateScale = false
self.backgroundNode = ASImageNode()
self.backgroundNode.displaysAsynchronously = false
self.backgroundNode.displayWithoutProcessing = true
self.backgroundNode = ASDisplayNode()
self.backgroundNode.cornerRadius = 11.0
self.iconNode = ASImageNode()
self.iconNode.displaysAsynchronously = false
@ -127,6 +126,9 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
let iconUpdated = self.icon != icon
let isActiveUpdated = self.isActive != isActive
self.isActive = isActive
let iconSize = CGSize(width: 40.0, height: 40.0)
if self.theme != presentationData.theme || self.icon != icon {
self.theme = presentationData.theme
self.icon = icon
@ -141,7 +143,7 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
var colors: [String: UIColor] = [:]
var playOnce = false
var seekToEnd = false
let iconColor = presentationData.theme.list.itemCheckColors.foregroundColor
let iconColor = presentationData.theme.list.itemAccentColor
switch icon {
case .voiceChat:
animationName = "anim_profilevc"
@ -198,7 +200,6 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
self.referenceNode.addSubnode(animationNode)
self.animationNode = animationNode
}
animationNode.frame = CGRect(origin: CGPoint(), size: size)
} else if let animationNode = self.animationNode {
self.animationNode = nil
animationNode.removeFromSupernode()
@ -210,11 +211,12 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
self.animationNode?.seekToEnd()
}
self.backgroundNode.image = generateFilledCircleImage(diameter: 40.0, color: presentationData.theme.list.itemAccentColor)
self.iconNode.image = generateImage(CGSize(width: 40.0, height: 40.0), contextGenerator: { size, context in
self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size))
self.iconNode.image = generateImage(iconSize, contextGenerator: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setBlendMode(.normal)
context.setFillColor(presentationData.theme.list.itemCheckColors.foregroundColor.cgColor)
context.setFillColor(iconColor.cgColor)
let imageName: String?
switch icon {
case .message:
@ -246,24 +248,26 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
})
}
let alpha: CGFloat = isActive ? 1.0 : 0.3
if isActiveUpdated, !self.containerNode.alpha.isZero {
if isActiveUpdated {
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
alphaTransition.updateAlpha(node: self.backgroundNode, alpha: isActive ? 1.0 : 0.3)
if !isExpanded {
alphaTransition.updateAlpha(node: self.textNode, alpha: isActive ? 1.0 : 0.3)
alphaTransition.updateAlpha(node: self.iconNode, alpha: isActive ? 1.0 : 0.3)
if let animationNode = self.animationNode {
alphaTransition.updateAlpha(node: animationNode, alpha: isActive ? 1.0 : 0.3)
}
alphaTransition.updateAlpha(node: self.textNode, alpha: isActive ? 1.0 : 0.3)
}
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(12.0), textColor: presentationData.theme.list.itemAccentColor)
self.textNode.attributedText = NSAttributedString(string: text.lowercased(), font: Font.regular(11.0), textColor: presentationData.theme.list.itemAccentColor)
self.accessibilityLabel = text
let titleSize = self.textNode.updateLayout(CGSize(width: 120.0, height: .greatestFiniteMagnitude))
transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: size))
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: size))
transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(), size: size))
transition.updateFrameAdditiveToCenter(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: size.height + 6.0), size: titleSize))
transition.updateAlpha(node: self.textNode, alpha: isExpanded ? 0.0 : alpha)
transition.updateFrame(node: self.iconNode, frame: CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: 1.0), size: iconSize))
if let animationNode = self.animationNode {
transition.updateFrame(node: animationNode, frame: CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: 1.0), size: iconSize))
}
transition.updateFrameAdditiveToCenter(node: self.textNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: size.height - titleSize.height - 9.0), size: titleSize))
self.referenceNode.frame = self.containerNode.bounds
}
@ -1267,9 +1271,9 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
if self.theme !== presentationData.theme {
self.theme = presentationData.theme
if isSettings {
self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
}
self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
self.textNode.textField.textColor = presentationData.theme.list.itemPrimaryTextColor
self.textNode.textField.keyboardAppearance = presentationData.theme.rootController.keyboardColor.keyboardAppearance
self.textNode.textField.tintColor = presentationData.theme.list.itemAccentColor
@ -1287,7 +1291,7 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
self.textNode.textField.text = updateText
}
if !hasPrevious && isSettings {
if !hasPrevious {
self.topSeparator.isHidden = true
}
self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
@ -1325,12 +1329,14 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
}
final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode, ASEditableTextNodeDelegate {
private let backgroundNode: ASDisplayNode
private let textNode: EditableTextNode
private let textNodeContainer: ASDisplayNode
private let measureTextNode: ImmediateTextNode
private let clearIconNode: ASImageNode
private let clearButtonNode: HighlightableButtonNode
private let topSeparator: ASDisplayNode
private let maskNode: ASImageNode
private let requestUpdateHeight: () -> Void
@ -1346,6 +1352,8 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
init(requestUpdateHeight: @escaping () -> Void) {
self.requestUpdateHeight = requestUpdateHeight
self.backgroundNode = ASDisplayNode()
self.textNode = EditableTextNode()
self.textNode.clipsToBounds = false
self.textNode.textView.clipsToBounds = false
@ -1365,13 +1373,18 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
self.clearButtonNode = HighlightableButtonNode()
self.clearButtonNode.isHidden = true
self.maskNode = ASImageNode()
self.maskNode.isUserInteractionEnabled = false
super.init()
self.addSubnode(self.backgroundNode)
self.textNodeContainer.addSubnode(self.textNode)
self.addSubnode(self.textNodeContainer)
self.addSubnode(self.clearIconNode)
self.addSubnode(self.clearButtonNode)
self.addSubnode(self.topSeparator)
self.addSubnode(self.maskNode)
self.clearButtonNode.addTarget(self, action: #selector(self.clearButtonPressed), forControlEvents: .touchUpInside)
self.clearButtonNode.highligthedChanged = { [weak self] highlighted in
@ -1411,8 +1424,10 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
if self.theme !== presentationData.theme {
self.theme = presentationData.theme
let textColor = presentationData.theme.list.itemPrimaryTextColor
self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
let textColor = presentationData.theme.list.itemPrimaryTextColor
self.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: titleFont, NSAttributedString.Key.foregroundColor.rawValue: textColor]
self.textNode.keyboardAppearance = presentationData.theme.rootController.keyboardColor.keyboardAppearance
self.textNode.tintColor = presentationData.theme.list.itemAccentColor
@ -1425,7 +1440,9 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
}
self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
self.topSeparator.frame = CGRect(origin: CGPoint(x: safeInset + (hasPrevious ? 16.0 : 0.0), y: 0.0), size: CGSize(width: width, height: UIScreenPixel))
let separatorX = safeInset + (hasPrevious ? 16.0 : 0.0)
self.topSeparator.frame = CGRect(origin: CGPoint(x: separatorX, y: 0.0), size: CGSize(width: width - separatorX - safeInset, height: UIScreenPixel))
let attributedPlaceholderText = NSAttributedString(string: placeholder, font: titleFont, textColor: presentationData.theme.list.itemPlaceholderTextColor)
if self.textNode.attributedPlaceholderText == nil || !self.textNode.attributedPlaceholderText!.isEqual(to: attributedPlaceholderText) {
@ -1458,6 +1475,15 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
self.textNodeContainer.frame = textNodeFrame
self.textNode.frame = CGRect(origin: CGPoint(), size: textNodeFrame.size)
self.backgroundNode.frame = CGRect(origin: CGPoint(x: safeInset, y: 0.0), size: CGSize(width: max(1.0, width - safeInset * 2.0), height: height))
let hasCorners = safeInset > 0.0 && (!hasPrevious || !hasNext)
let hasTopCorners = hasCorners && !hasPrevious
let hasBottomCorners = hasCorners && !hasNext
self.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
self.maskNode.frame = CGRect(origin: CGPoint(x: safeInset, y: 0.0), size: CGSize(width: width - safeInset - safeInset, height: height))
return height
}
@ -1560,10 +1586,7 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode {
func update(width: CGFloat, safeInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, peer: Peer?, cachedData: CachedPeerData?, isContact: Bool, isSettings: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) -> CGFloat {
let avatarSize: CGFloat = isModalOverlay ? 200.0 : 100.0
var avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize))
if isSettings {
avatarFrame = avatarFrame.offsetBy(dx: 0.0, dy: 3.0)
}
let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 13.0), size: CGSize(width: avatarSize, height: avatarSize))
transition.updateFrameAdditiveToCenter(node: self.avatarNode, frame: CGRect(origin: avatarFrame.center, size: CGSize()))
var contentHeight: CGFloat = statusBarHeight + 10.0 + avatarSize + 20.0
@ -1691,12 +1714,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
private let videoCallsEnabled: Bool
private(set) var isAvatarExpanded: Bool
private(set) var twoLineInfo = false
var skipCollapseCompletion = false
var ignoreCollapse = false
let avatarListNode: PeerInfoAvatarListNode
let buttonsContainerNode: SparseNode
let regularContentNode: PeerInfoHeaderRegularContentNode
let editingContentNode: PeerInfoHeaderEditingContentNode
let avatarOverlayNode: PeerInfoEditingAvatarOverlayNode
@ -1735,6 +1758,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var navigationTransition: PeerInfoHeaderNavigationTransition?
var backgroundAlpha: CGFloat = 1.0
var updateHeaderAlpha: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
init(context: AccountContext, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isSettings: Bool) {
@ -1774,6 +1798,9 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.usernameNode = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
self.usernameNode.displaysAsynchronously = false
self.buttonsContainerNode = SparseNode()
self.buttonsContainerNode.clipsToBounds = true
self.regularContentNode = PeerInfoHeaderRegularContentNode()
var requestUpdateLayoutImpl: (() -> Void)?
self.editingContentNode = PeerInfoHeaderEditingContentNode(context: context, requestUpdateLayout: {
@ -1813,28 +1840,22 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self?.requestUpdateLayout?()
}
self.addSubnode(self.buttonsContainerNode)
self.addSubnode(self.backgroundNode)
self.addSubnode(self.expandedBackgroundNode)
self.titleNodeContainer.addSubnode(self.titleNode)
self.subtitleNodeContainer.addSubnode(self.subtitleNode)
self.subtitleNodeContainer.addSubnode(self.panelSubtitleNode)
self.usernameNodeContainer.addSubnode(self.usernameNode)
if !self.isSettings {
self.regularContentNode.addSubnode(self.titleNodeContainer)
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
self.regularContentNode.addSubnode(self.subtitleNodeRawContainer)
self.regularContentNode.addSubnode(self.usernameNodeContainer)
self.regularContentNode.addSubnode(self.usernameNodeRawContainer)
}
self.regularContentNode.addSubnode(self.avatarListNode)
self.regularContentNode.addSubnode(self.avatarListNode.listContainerNode.controlsClippingOffsetNode)
if self.isSettings {
self.regularContentNode.addSubnode(self.titleNodeContainer)
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
self.regularContentNode.addSubnode(self.subtitleNodeRawContainer)
self.regularContentNode.addSubnode(self.usernameNodeContainer)
self.regularContentNode.addSubnode(self.usernameNodeRawContainer)
}
self.regularContentNode.addSubnode(self.titleNodeContainer)
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
self.regularContentNode.addSubnode(self.subtitleNodeRawContainer)
self.regularContentNode.addSubnode(self.usernameNodeContainer)
self.regularContentNode.addSubnode(self.usernameNodeRawContainer)
self.addSubnode(self.regularContentNode)
self.addSubnode(self.editingContentNode)
self.addSubnode(self.avatarOverlayNode)
@ -1956,7 +1977,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
self.avatarListNode.listContainerNode.updateEntryIsHidden(entry: entry)
}
var initializedCredibilityIcon = false
func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, isMediaOnly: Bool, contentOffset: CGFloat, paneContainerY: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, notificationSettings: TelegramPeerNotificationSettings?, statusData: PeerInfoStatusData?, panelStatusData: PeerInfoStatusData?, isSecretChat: Bool, isContact: Bool, isSettings: Bool, state: PeerInfoState, transition: ContainedViewLayoutTransition, additive: Bool) -> CGFloat {
self.state = state
@ -2011,6 +2032,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0
self.buttonsContainerNode.alpha = self.regularContentNode.alpha
self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0
let editingContentHeight = self.editingContentNode.update(width: width, safeInset: containerInset, statusBarHeight: statusBarHeight, navigationHeight: navigationHeight, isModalOverlay: isModalOverlay, peer: state.isEditing ? peer : nil, cachedData: cachedData, isContact: isContact, isSettings: isSettings, presentationData: presentationData, transition: transition)
@ -2027,6 +2049,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.backgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
let headerBackgroundColor: UIColor = presentationData.theme.list.blocksBackgroundColor
var effectiveSeparatorAlpha: CGFloat
if let navigationTransition = self.navigationTransition, let sourceAvatarNode = (navigationTransition.sourceNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode)?.avatarNode {
transitionSourceHeight = navigationTransition.sourceNavigationBar.backgroundNode.bounds.height
transitionFraction = navigationTransition.fraction
@ -2034,15 +2058,18 @@ final class PeerInfoHeaderNode: ASDisplayNode {
transitionSourceTitleFrame = navigationTransition.sourceTitleFrame
transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame
self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor.mixedWith(presentationData.theme.list.itemBlocksBackgroundColor, alpha: 1.0 - transitionFraction), forceKeepBlur: true, transition: transition)
self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.blurredBackgroundColor.mixedWith(headerBackgroundColor, alpha: 1.0 - transitionFraction), forceKeepBlur: true, transition: transition)
effectiveSeparatorAlpha = transitionFraction
if self.isAvatarExpanded, case .animated = transition, transitionFraction == 1.0 {
self.avatarListNode.animateAvatarCollapse(transition: transition)
}
} else {
let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / (112.0 + avatarSize)))
let contentOffset = max(0.0, contentOffset - 140.0)
let backgroundTransitionFraction: CGFloat = max(0.0, min(1.0, contentOffset / 30.0))
self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.opaqueBackgroundColor.mixedWith(presentationData.theme.list.itemBlocksBackgroundColor, alpha: 1.0 - backgroundTransitionFraction), forceKeepBlur: true, transition: transition)
self.expandedBackgroundNode.updateColor(color: presentationData.theme.rootController.navigationBar.opaqueBackgroundColor.mixedWith(headerBackgroundColor, alpha: 1.0 - backgroundTransitionFraction), forceKeepBlur: true, transition: transition)
effectiveSeparatorAlpha = backgroundTransitionFraction
}
self.avatarListNode.avatarContainerNode.updateTransitionFraction(transitionFraction, transition: transition)
@ -2062,13 +2089,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.navigationBackgroundBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.opaqueBackgroundColor
self.navigationSeparatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor
let separatorAlpha: CGFloat = state.isEditing && self.isSettings ? min(1.0, contentOffset / (navigationHeight * 0.5)) : 0.0
transition.updateAlpha(node: self.navigationBackgroundBackgroundNode, alpha: 1.0 - separatorAlpha)
transition.updateAlpha(node: self.navigationSeparatorNode, alpha: separatorAlpha)
let navigationSeparatorAlpha: CGFloat = state.isEditing && self.isSettings ? min(1.0, contentOffset / (navigationHeight * 0.5)) : 0.0
transition.updateAlpha(node: self.navigationBackgroundBackgroundNode, alpha: 1.0 - navigationSeparatorAlpha)
transition.updateAlpha(node: self.navigationSeparatorNode, alpha: navigationSeparatorAlpha)
self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
let defaultButtonSize: CGFloat = 40.0
let expandedAvatarControlsHeight: CGFloat = 61.0
let expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight)
let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight)
@ -2105,13 +2131,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
title = " "
}
}
if self.isSettings {
// if self.isSettings {
titleString = NSAttributedString(string: title, font: Font.medium(29.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
smallTitleString = NSAttributedString(string: title, font: Font.semibold(28.0), textColor: .white)
} else {
titleString = NSAttributedString(string: title, font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
smallTitleString = titleString
}
// } else {
// titleString = NSAttributedString(string: title, font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
// smallTitleString = titleString
// }
if self.isSettings, let user = peer as? TelegramUser {
var subtitle = formatPhoneNumber(user.phone ?? "")
@ -2128,8 +2154,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} else {
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
}
subtitleString = NSAttributedString(string: statusData.text, font: Font.regular(15.0), textColor: subtitleColor)
smallSubtitleString = subtitleString
smallSubtitleString = NSAttributedString(string: statusData.text, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.7))
subtitleString = NSAttributedString(string: statusData.text, font: Font.regular(17.0), textColor: subtitleColor)
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
if let panelStatusData = panelStatusData {
@ -2139,7 +2165,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} else {
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
}
panelSubtitleString = NSAttributedString(string: panelStatusData.text, font: Font.regular(15.0), textColor: subtitleColor)
panelSubtitleString = NSAttributedString(string: panelStatusData.text, font: Font.regular(17.0), textColor: subtitleColor)
}
} else {
subtitleString = NSAttributedString(string: " ", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
@ -2154,11 +2180,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
}
let textSideInset: CGFloat = 44.0
var expandedAvatarHeight: CGFloat = expandedAvatarListSize.height
if !self.isSettings {
expandedAvatarHeight += expandedAvatarControlsHeight
}
let textSideInset: CGFloat = 36.0
let expandedAvatarHeight: CGFloat = expandedAvatarListSize.height
let titleConstrainedSize = CGSize(width: width - textSideInset * 2.0 - (isVerified ? 16.0 : 0.0), height: .greatestFiniteMagnitude)
@ -2170,13 +2193,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let subtitleNodeLayout = self.subtitleNode.updateLayout(states: [
TitleNodeStateRegular: MultiScaleTextState(attributedText: subtitleString, constrainedSize: titleConstrainedSize),
TitleNodeStateExpanded: MultiScaleTextState(attributedText: smallSubtitleString, constrainedSize: self.isSettings ? titleConstrainedSize : CGSize(width: titleConstrainedSize.width - 82.0, height: titleConstrainedSize.height))
TitleNodeStateExpanded: MultiScaleTextState(attributedText: smallSubtitleString, constrainedSize: titleConstrainedSize)
], mainState: TitleNodeStateRegular)
self.subtitleNode.accessibilityLabel = subtitleString.string
let panelSubtitleNodeLayout = self.panelSubtitleNode.updateLayout(states: [
TitleNodeStateRegular: MultiScaleTextState(attributedText: panelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize),
TitleNodeStateExpanded: MultiScaleTextState(attributedText: panelSubtitleString ?? subtitleString, constrainedSize: CGSize(width: titleConstrainedSize.width - 82.0, height: titleConstrainedSize.height))
TitleNodeStateExpanded: MultiScaleTextState(attributedText: panelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize)
], mainState: TitleNodeStateRegular)
self.panelSubtitleNode.accessibilityLabel = (panelSubtitleString ?? subtitleString).string
@ -2186,10 +2209,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
], mainState: TitleNodeStateRegular)
self.usernameNode.accessibilityLabel = usernameString.string
var avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 10.0), size: CGSize(width: avatarSize, height: avatarSize))
if isSettings {
avatarFrame = avatarFrame.offsetBy(dx: 0.0, dy: 3.0)
}
let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 13.0), size: CGSize(width: avatarSize, height: avatarSize))
let avatarCenter = CGPoint(x: (1.0 - transitionFraction) * avatarFrame.midX + transitionFraction * transitionSourceAvatarFrame.midX, y: (1.0 - transitionFraction) * avatarFrame.midY + transitionFraction * transitionSourceAvatarFrame.midY)
let titleSize = titleNodeLayout[TitleNodeStateRegular]!.size
@ -2208,34 +2228,25 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let subtitleFrame: CGRect
let usernameFrame: CGRect
let usernameSpacing: CGFloat = 4.0
var twoLineInfo = false
if self.isSettings {
transition.updateFrame(node: self.avatarListNode.listContainerNode.bottomShadowNode, frame: CGRect(origin: CGPoint(x: 0.0, y: expandedAvatarHeight - 70.0), size: CGSize(width: width, height: 70.0)))
}
transition.updateFrame(node: self.avatarListNode.listContainerNode.bottomShadowNode, frame: CGRect(origin: CGPoint(x: 0.0, y: expandedAvatarHeight - 70.0), size: CGSize(width: width, height: 70.0)))
if self.isAvatarExpanded {
let minTitleSize = CGSize(width: titleSize.width * 0.7, height: titleSize.height * 0.7)
let minTitleFrame: CGRect
if self.isSettings {
minTitleFrame = CGRect(origin: CGPoint(x: 16.0, y: expandedAvatarHeight - 58.0 - UIScreenPixel + (subtitleSize.height.isZero ? 10.0 : 0.0)), size: minTitleSize)
} else {
minTitleFrame = CGRect(origin: CGPoint(x: 16.0, y: expandedAvatarHeight - expandedAvatarControlsHeight + 9.0 + (subtitleSize.height.isZero ? 10.0 : 0.0)), size: minTitleSize)
}
minTitleFrame = CGRect(origin: CGPoint(x: 16.0, y: expandedAvatarHeight - 58.0 - UIScreenPixel + (subtitleSize.height.isZero ? 10.0 : 0.0)), size: minTitleSize)
titleFrame = CGRect(origin: CGPoint(x: minTitleFrame.midX - titleSize.width / 2.0, y: minTitleFrame.midY - titleSize.height / 2.0), size: titleSize)
if self.isSettings {
subtitleFrame = CGRect(origin: CGPoint(x: 16.0, y: minTitleFrame.maxY + 2.0), size: subtitleSize)
} else {
subtitleFrame = CGRect(origin: CGPoint(x: 16.0, y: minTitleFrame.maxY + 4.0), size: subtitleSize)
}
subtitleFrame = CGRect(origin: CGPoint(x: 16.0, y: minTitleFrame.maxY + 2.0), size: subtitleSize)
usernameFrame = CGRect(origin: CGPoint(x: width - usernameSize.width - 16.0, y: minTitleFrame.midY - usernameSize.height / 2.0), size: usernameSize)
} else {
titleFrame = CGRect(origin: CGPoint(x: floor((width - titleSize.width) / 2.0), y: avatarFrame.maxY + 7.0 + (subtitleSize.height.isZero ? 11.0 : 0.0)), size: titleSize)
if self.isSettings {
titleFrame = titleFrame.offsetBy(dx: 0.0, dy: 11.0)
}
titleFrame = titleFrame.offsetBy(dx: 0.0, dy: 11.0)
let totalSubtitleWidth = subtitleSize.width + usernameSpacing + usernameSize.width
twoLineInfo = false
if usernameSize.width == 0.0 || twoLineInfo {
if usernameSize.width == 0.0 {
subtitleFrame = CGRect(origin: CGPoint(x: floor((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize)
usernameFrame = CGRect(origin: CGPoint(x: floor((width - usernameSize.width) / 2.0), y: subtitleFrame.maxY + 1.0), size: usernameSize)
} else {
@ -2243,7 +2254,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
usernameFrame = CGRect(origin: CGPoint(x: subtitleFrame.maxX + usernameSpacing, y: titleFrame.maxY + 1.0), size: usernameSize)
}
}
self.twoLineInfo = twoLineInfo
let singleTitleLockOffset: CGFloat = (peer?.id == self.context.account.peerId || subtitleSize.height.isZero) ? 8.0 : 0.0
@ -2253,7 +2263,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let titleOffset = -min(titleCollapseOffset, contentOffset)
let titleCollapseFraction = max(0.0, min(1.0, contentOffset / titleCollapseOffset))
let titleMinScale: CGFloat = self.isSettings ? 0.6 : 0.7
let titleMinScale: CGFloat = 0.6
let subtitleMinScale: CGFloat = 0.8
let avatarMinScale: CGFloat = 0.7
@ -2273,6 +2283,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance
}
let secondarySeparatorAlpha = 1.0 - effectiveAreaExpansionFraction
if self.navigationTransition == nil && !self.isSettings && effectiveSeparatorAlpha == 1.0 && secondarySeparatorAlpha < 1.0 {
effectiveSeparatorAlpha = secondarySeparatorAlpha
}
transition.updateAlpha(node: self.separatorNode, alpha: effectiveSeparatorAlpha)
self.titleNode.update(stateFractions: [
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
@ -2285,12 +2301,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
if self.isSettings {
subtitleAlpha = 1.0 - titleCollapseFraction
panelSubtitleAlpha = 0.0
var headerBackgroundAlpha: CGFloat = 0.0
if !state.isEditing && titleCollapseFraction >= 0.8 {
headerBackgroundAlpha = (titleCollapseFraction - 0.8) / 0.2
}
self.updateHeaderAlpha?(headerBackgroundAlpha, transition)
} else {
if (panelSubtitleString ?? subtitleString).string != subtitleString.string {
subtitleAlpha = 1.0 - effectiveAreaExpansionFraction
@ -2422,23 +2432,19 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self.avatarListNode.avatarContainerNode.canAttachVideo = false
}
var panelWithAvatarHeight: CGFloat = (self.isSettings ? 40.0 : 112.0) + avatarSize
if twoLineInfo {
panelWithAvatarHeight += 17.0
}
let buttonsCollapseStart = titleCollapseOffset
let buttonsCollapseEnd = panelWithAvatarHeight - (navigationHeight - statusBarHeight) + 10.0
let buttonsCollapseFraction = max(0.0, contentOffset - buttonsCollapseStart) / (buttonsCollapseEnd - buttonsCollapseStart)
let panelWithAvatarHeight: CGFloat = 40.0 + avatarSize
let rawHeight: CGFloat
let height: CGFloat
let maxY: CGFloat
if self.isAvatarExpanded {
rawHeight = expandedAvatarHeight
height = max(navigationHeight, rawHeight - contentOffset)
maxY = height
} else {
rawHeight = navigationHeight + panelWithAvatarHeight
height = navigationHeight + max(0.0, panelWithAvatarHeight - contentOffset)
maxY = navigationHeight + panelWithAvatarHeight - contentOffset
}
let apparentHeight = (1.0 - transitionFraction) * height + transitionFraction * transitionSourceHeight
@ -2474,12 +2480,14 @@ final class PeerInfoHeaderNode: ASDisplayNode {
} else {
let titleScale: CGFloat
let subtitleScale: CGFloat
var subtitleOffset: CGFloat = 0.0
if self.isAvatarExpanded {
titleScale = 0.7
subtitleScale = 1.0
} else {
titleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * titleMinScale
subtitleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * subtitleMinScale
subtitleOffset = titleCollapseFraction * -2.0
}
let rawTitleFrame = titleFrame
@ -2498,6 +2506,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
var subtitleCenter = rawSubtitleFrame.center
subtitleCenter.x = rawTitleFrame.center.x + (subtitleCenter.x - rawTitleFrame.center.x) * subtitleScale
subtitleCenter.y += subtitleOffset
transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: CGRect(origin: subtitleCenter, size: CGSize()).offsetBy(dx: 0.0, dy: titleOffset))
var usernameCenter = rawUsernameFrame.center
@ -2513,63 +2522,16 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
}
let buttonSpacing: CGFloat
if self.isAvatarExpanded {
buttonSpacing = 16.0
} else {
let normWidth = min(width, containerHeight)
let buttonSpacingValue = floor((normWidth - floor(CGFloat(buttonKeys.count) * defaultButtonSize)) / CGFloat(buttonKeys.count + 1))
buttonSpacing = min(buttonSpacingValue, 160.0)
}
let buttonSpacing: CGFloat = 12.0
var buttonRightOrigin = CGPoint(x: width - containerInset, y: maxY + 25.0 - navigationHeight - UIScreenPixel)
let buttonWidth = (width - containerInset * 2.0 + buttonSpacing) / CGFloat(buttonKeys.count) - buttonSpacing
let expandedButtonSize: CGFloat = 32.0
let buttonsWidth = buttonSpacing * CGFloat(buttonKeys.count - 1) + CGFloat(buttonKeys.count) * defaultButtonSize
var buttonRightOrigin: CGPoint
if self.isAvatarExpanded {
buttonRightOrigin = CGPoint(x: width - 16.0, y: apparentHeight - 74.0)
} else {
buttonRightOrigin = CGPoint(x: floor((width - buttonsWidth) / 2.0) + buttonsWidth, y: apparentHeight - 74.0)
}
let buttonsScale: CGFloat
let buttonsAlpha: CGFloat
let apparentButtonSize: CGFloat
let buttonsVerticalOffset: CGFloat
let apparentButtonSize = CGSize(width: buttonWidth, height: 58.0)
let buttonsAlpha: CGFloat = 1.0
let buttonsVerticalOffset: CGFloat = 0.0
var buttonsAlphaTransition = transition
let buttonsAlphaTransition = transition
if self.navigationTransition != nil {
if case let .animated(duration, curve) = transition, transitionFraction >= 1.0 - CGFloat.ulpOfOne {
buttonsAlphaTransition = .animated(duration: duration * 0.6, curve: curve)
}
if self.isAvatarExpanded {
apparentButtonSize = expandedButtonSize
} else {
apparentButtonSize = defaultButtonSize
}
let neutralButtonsScale = apparentButtonSize / defaultButtonSize
buttonsScale = (1.0 - transitionFraction) * neutralButtonsScale + 0.2 * transitionFraction
buttonsAlpha = 1.0 - transitionFraction
let neutralButtonsOffset: CGFloat
if self.isAvatarExpanded {
neutralButtonsOffset = 74.0 - 15.0 - defaultButtonSize + (defaultButtonSize - apparentButtonSize) / 2.0
} else {
neutralButtonsOffset = (1.0 - buttonsScale) * apparentButtonSize
}
buttonsVerticalOffset = (1.0 - transitionFraction) * neutralButtonsOffset + ((1.0 - buttonsScale) * apparentButtonSize) * transitionFraction
} else {
apparentButtonSize = self.isAvatarExpanded ? expandedButtonSize : defaultButtonSize
if self.isAvatarExpanded {
buttonsScale = apparentButtonSize / defaultButtonSize
buttonsVerticalOffset = 74.0 - 15.0 - defaultButtonSize + (defaultButtonSize - apparentButtonSize) / 2.0
} else {
buttonsScale = (1.0 - buttonsCollapseFraction) * 1.0 + 0.2 * buttonsCollapseFraction
buttonsVerticalOffset = (1.0 - buttonsScale) * apparentButtonSize
}
buttonsAlpha = 1.0 - buttonsCollapseFraction
}
let buttonsScaledOffset = (defaultButtonSize - apparentButtonSize) / 2.0
for buttonKey in buttonKeys.reversed() {
let buttonNode: PeerInfoHeaderButtonNode
var wasAdded = false
@ -2581,10 +2543,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
self?.buttonPressed(buttonNode, gesture: gesture)
})
self.buttonNodes[buttonKey] = buttonNode
self.regularContentNode.addSubnode(buttonNode)
self.buttonsContainerNode.addSubnode(buttonNode)
}
let buttonFrame = CGRect(origin: CGPoint(x: buttonRightOrigin.x - defaultButtonSize + buttonsScaledOffset, y: buttonRightOrigin.y), size: CGSize(width: defaultButtonSize, height: defaultButtonSize))
let buttonFrame = CGRect(origin: CGPoint(x: buttonRightOrigin.x - apparentButtonSize.width, y: buttonRightOrigin.y), size: apparentButtonSize)
let buttonTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition
let apparentButtonFrame = buttonFrame.offsetBy(dx: 0.0, dy: buttonsVerticalOffset)
@ -2642,39 +2604,23 @@ final class PeerInfoHeaderNode: ASDisplayNode {
isActive = buttonKey == highlightedButton
}
buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isActive: isActive, isExpanded: self.isAvatarExpanded, presentationData: presentationData, transition: buttonTransition)
transition.updateSublayerTransformScaleAdditive(node: buttonNode, scale: buttonsScale)
buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isActive: isActive, isExpanded: false, presentationData: presentationData, transition: buttonTransition)
if wasAdded {
buttonNode.alpha = 0.0
}
buttonsAlphaTransition.updateAlpha(node: buttonNode, alpha: buttonsAlpha)
let hiddenWhileExpanded: Bool
if buttonKeys.count > 3 {
hiddenWhileExpanded = peerInfoHeaderButtonIsHiddenWhileExpanded(buttonKey: buttonKey, isOpenedFromChat: self.isOpenedFromChat)
} else {
hiddenWhileExpanded = false
}
if self.isAvatarExpanded, hiddenWhileExpanded {
if case .mute = buttonKey, buttonNode.containerNode.alpha.isZero, additive {
if case let .animated(duration, curve) = transition {
ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 0.0)
} else {
transition.updateAlpha(node: buttonNode.containerNode, alpha: 0.0)
}
} else {
if case .mute = buttonKey, buttonNode.containerNode.alpha.isZero, additive {
if case let .animated(duration, curve) = transition {
ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
} else {
transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
}
ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
} else {
transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
}
buttonRightOrigin.x -= apparentButtonSize + buttonSpacing
} else {
transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
}
buttonRightOrigin.x -= apparentButtonSize.width + buttonSpacing
}
for key in self.buttonNodes.keys {
@ -2690,11 +2636,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let resolvedRegularHeight: CGFloat
if self.isAvatarExpanded {
if self.isSettings {
resolvedRegularHeight = expandedAvatarListSize.height
} else {
resolvedRegularHeight = expandedAvatarListSize.height + expandedAvatarControlsHeight
}
resolvedRegularHeight = expandedAvatarListSize.height
} else {
resolvedRegularHeight = panelWithAvatarHeight + navigationHeight
}
@ -2703,6 +2645,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
let separatorFrame: CGRect
let resolvedHeight: CGFloat
if state.isEditing {
resolvedHeight = editingContentHeight
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + max(navigationHeight, resolvedHeight - contentOffset)), size: CGSize(width: width, height: 2000.0))
@ -2714,6 +2657,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
}
transition.updateFrame(node: self.regularContentNode, frame: CGRect(origin: CGPoint(), size: CGSize(width: width, height: resolvedHeight)))
transition.updateFrame(node: self.buttonsContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationHeight + UIScreenPixel), size: CGSize(width: width, height: resolvedHeight - navigationHeight + 180.0)))
if additive {
transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame)

View File

@ -92,6 +92,7 @@ enum PeerInfoMembersDataState: Equatable {
}
struct PeerInfoMembersState: Equatable {
var canAddMembers: Bool
var members: [PeerInfoMember]
var dataState: PeerInfoMembersDataState
}
@ -126,6 +127,7 @@ private final class PeerInfoMembersContextImpl {
private let context: AccountContext
private let peerId: PeerId
private var canAddMembers = false
private var members: [PeerInfoMember] = []
private var dataState: PeerInfoMembersDataState = .loading(isInitial: true)
private var removingMemberIds: [PeerId: Disposable] = [:]
@ -135,7 +137,7 @@ private final class PeerInfoMembersContextImpl {
return self.stateValue.get()
}
private let disposable = MetaDisposable()
private let peerDisposable = MetaDisposable()
private var channelMembersControl: PeerChannelMemberCategoryControl?
init(queue: Queue, context: AccountContext, peerId: PeerId) {
@ -170,8 +172,28 @@ private final class PeerInfoMembersContextImpl {
})
self.disposable.set(disposable)
self.channelMembersControl = control
self.peerDisposable.set((context.account.postbox.peerView(id: peerId)
|> deliverOn(self.queue)).start(next: { [weak self] view in
guard let strongSelf = self else {
return
}
if let channel = peerViewMainPeer(view) as? TelegramChannel {
var canAddMembers = false
switch channel.info {
case .broadcast:
break
case .group:
if channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) {
canAddMembers = true
}
}
strongSelf.canAddMembers = canAddMembers
strongSelf.pushState()
}
}))
} else if peerId.namespace == Namespaces.Peer.CloudGroup {
disposable.set((context.account.postbox.peerView(id: peerId)
self.disposable.set((context.account.postbox.peerView(id: peerId)
|> deliverOn(self.queue)).start(next: { [weak self] view in
guard let strongSelf = self, let cachedData = view.cachedData as? CachedGroupData, let participantsData = cachedData.participants else {
return
@ -195,6 +217,21 @@ private final class PeerInfoMembersContextImpl {
unsortedMembers.append(.legacyGroupMember(peer: RenderedPeer(peer: peer), role: role, invitedBy: invitedBy, presence: view.peerPresences[participant.peerId] as? TelegramUserPresence))
}
}
if let group = peerViewMainPeer(view) as? TelegramGroup {
var canAddMembers = false
switch group.role {
case .admin, .creator:
canAddMembers = true
case .member:
break
}
if !group.hasBannedPermission(.banAddMembers) {
canAddMembers = true
}
strongSelf.canAddMembers = canAddMembers
}
strongSelf.members = membersSortedByPresence(unsortedMembers, accountPeerId: strongSelf.context.account.peerId)
strongSelf.dataState = .ready(canLoadMore: false)
strongSelf.pushState()
@ -207,13 +244,14 @@ private final class PeerInfoMembersContextImpl {
deinit {
self.disposable.dispose()
self.peerDisposable.dispose()
}
private func pushState() {
if self.removingMemberIds.isEmpty {
self.stateValue.set(.single(PeerInfoMembersState(members: self.members, dataState: self.dataState)))
self.stateValue.set(.single(PeerInfoMembersState(canAddMembers: self.canAddMembers, members: self.members, dataState: self.dataState)))
} else {
self.stateValue.set(.single(PeerInfoMembersState(members: self.members.filter { member in
self.stateValue.set(.single(PeerInfoMembersState(canAddMembers: self.canAddMembers, members: self.members.filter { member in
return self.removingMemberIds[member.id] == nil
}, dataState: self.dataState)))
}

View File

@ -383,6 +383,7 @@ private final class PeerInfoPendingPane {
chatControllerInteraction: ChatControllerInteraction,
data: PeerInfoScreenData,
openPeerContextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void,
openAddMemberAction: @escaping () -> Void,
requestPerformPeerMemberAction: @escaping (PeerInfoMember, PeerMembersListAction) -> Void,
peerId: PeerId,
key: PeerInfoPaneKey,
@ -423,7 +424,9 @@ private final class PeerInfoPendingPane {
paneNode = PeerInfoGroupsInCommonPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, openPeerContextAction: openPeerContextAction, groupsInCommonContext: data.groupsInCommon!)
case .members:
if case let .longList(membersContext) = data.members {
paneNode = PeerInfoMembersPaneNode(context: context, peerId: peerId, membersContext: membersContext, action: { member, action in
paneNode = PeerInfoMembersPaneNode(context: context, peerId: peerId, membersContext: membersContext, addMemberAction: {
openAddMemberAction()
}, action: { member, action in
requestPerformPeerMemberAction(member, action)
})
} else {
@ -487,6 +490,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
var chatControllerInteraction: ChatControllerInteraction?
var openPeerContextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)?
var openAddMemberAction: (() -> Void)?
var requestPerformPeerMemberAction: ((PeerInfoMember, PeerMembersListAction) -> Void)?
var currentPaneUpdated: ((Bool) -> Void)?
@ -517,7 +521,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
super.init()
self.addSubnode(self.separatorNode)
// self.addSubnode(self.separatorNode)
self.addSubnode(self.coveringBackgroundNode)
self.addSubnode(self.tabsContainerNode)
self.addSubnode(self.tabsSeparatorNode)
@ -772,6 +776,9 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
openPeerContextAction: { [weak self] peer, node, gesture in
self?.openPeerContextAction?(peer, node, gesture)
},
openAddMemberAction: { [weak self] in
self?.openAddMemberAction?()
},
requestPerformPeerMemberAction: { [weak self] member, action in
self?.requestPerformPeerMemberAction?(member, action)
},

View File

@ -71,7 +71,7 @@ protocol PeerInfoScreenItem: AnyObject {
class PeerInfoScreenItemNode: ASDisplayNode, AccessibilityFocusableNode {
var bringToFrontForHighlight: (() -> Void)?
func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
preconditionFailure()
}
@ -110,18 +110,13 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode {
self.addSubnode(self.bottomSeparatorNode)
}
func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, items: [PeerInfoScreenItem], transition: ContainedViewLayoutTransition) -> CGFloat {
func update(width: CGFloat, safeInsets: UIEdgeInsets, hasCorners: Bool, presentationData: PresentationData, items: [PeerInfoScreenItem], transition: ContainedViewLayoutTransition) -> CGFloat {
self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
self.topSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
if safeInsets.left > 0.0 {
self.topSeparatorNode.isHidden = true
self.bottomSeparatorNode.isHidden = true
} else {
self.topSeparatorNode.isHidden = false
self.bottomSeparatorNode.isHidden = false
}
self.topSeparatorNode.isHidden = hasCorners
self.bottomSeparatorNode.isHidden = hasCorners
var contentHeight: CGFloat = 0.0
var contentWithBackgroundHeight: CGFloat = 0.0
@ -167,7 +162,7 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode {
bottomItem = items[i + 1]
}
let itemHeight = itemNode.update(width: width, safeInsets: safeInsets, presentationData: presentationData, item: item, topItem: topItem, bottomItem: bottomItem, transition: itemTransition)
let itemHeight = itemNode.update(width: width, safeInsets: safeInsets, presentationData: presentationData, item: item, topItem: topItem, bottomItem: bottomItem, hasCorners: hasCorners, transition: itemTransition)
let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight))
itemTransition.updateFrame(node: itemNode, frame: itemFrame)
if wasAdded {
@ -219,133 +214,6 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode {
}
}
private final class PeerInfoScreenDynamicItemSectionContainerNode: ASDisplayNode {
private let backgroundNode: ASDisplayNode
private let topSeparatorNode: ASDisplayNode
private let bottomSeparatorNode: ASDisplayNode
private var currentItems: [PeerInfoScreenItem] = []
private var itemNodes: [AnyHashable: PeerInfoScreenItemNode] = [:]
override init() {
self.backgroundNode = ASDisplayNode()
self.backgroundNode.isLayerBacked = true
self.topSeparatorNode = ASDisplayNode()
self.topSeparatorNode.isLayerBacked = true
self.bottomSeparatorNode = ASDisplayNode()
self.bottomSeparatorNode.isLayerBacked = true
super.init()
self.addSubnode(self.backgroundNode)
self.addSubnode(self.topSeparatorNode)
self.addSubnode(self.bottomSeparatorNode)
}
func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, items: [PeerInfoScreenItem], transition: ContainedViewLayoutTransition) -> CGFloat {
self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
self.topSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
var contentHeight: CGFloat = 0.0
var contentWithBackgroundHeight: CGFloat = 0.0
var contentWithBackgroundOffset: CGFloat = 0.0
for i in 0 ..< items.count {
let item = items[i]
let itemNode: PeerInfoScreenItemNode
var wasAdded = false
if let current = self.itemNodes[item.id] {
itemNode = current
} else {
wasAdded = true
itemNode = item.node()
self.itemNodes[item.id] = itemNode
self.addSubnode(itemNode)
itemNode.bringToFrontForHighlight = { [weak self, weak itemNode] in
guard let strongSelf = self, let itemNode = itemNode else {
return
}
strongSelf.view.bringSubviewToFront(itemNode.view)
}
}
let itemTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition
let topItem: PeerInfoScreenItem?
if i == 0 {
topItem = nil
} else if items[i - 1] is PeerInfoScreenHeaderItem {
topItem = nil
} else {
topItem = items[i - 1]
}
let bottomItem: PeerInfoScreenItem?
if i == items.count - 1 {
bottomItem = nil
} else if items[i + 1] is PeerInfoScreenCommentItem {
bottomItem = nil
} else {
bottomItem = items[i + 1]
}
let itemHeight = itemNode.update(width: width, safeInsets: safeInsets, presentationData: presentationData, item: item, topItem: topItem, bottomItem: bottomItem, transition: itemTransition)
let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight))
itemTransition.updateFrame(node: itemNode, frame: itemFrame)
if wasAdded {
itemNode.alpha = 0.0
transition.updateAlpha(node: itemNode, alpha: 1.0)
}
if item is PeerInfoScreenCommentItem {
} else {
contentWithBackgroundHeight += itemHeight
}
contentHeight += itemHeight
if item is PeerInfoScreenHeaderItem {
contentWithBackgroundOffset = contentHeight
}
}
var removeIds: [AnyHashable] = []
for (id, _) in self.itemNodes {
if !items.contains(where: { $0.id == id }) {
removeIds.append(id)
}
}
for id in removeIds {
if let itemNode = self.itemNodes.removeValue(forKey: id) {
transition.updateAlpha(node: itemNode, alpha: 0.0, completion: { [weak itemNode] _ in
itemNode?.removeFromSupernode()
})
}
}
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundOffset), size: CGSize(width: width, height: max(0.0, contentWithBackgroundHeight - contentWithBackgroundOffset))))
transition.updateFrame(node: self.topSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundOffset - UIScreenPixel), size: CGSize(width: width, height: UIScreenPixel)))
transition.updateFrame(node: self.bottomSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: contentWithBackgroundHeight), size: CGSize(width: width, height: UIScreenPixel)))
if contentHeight.isZero {
transition.updateAlpha(node: self.topSeparatorNode, alpha: 0.0)
transition.updateAlpha(node: self.bottomSeparatorNode, alpha: 0.0)
} else {
transition.updateAlpha(node: self.topSeparatorNode, alpha: 1.0)
transition.updateAlpha(node: self.bottomSeparatorNode, alpha: 1.0)
}
return contentHeight
}
func updateVisibleItems(in rect: CGRect) {
}
}
final class PeerInfoSelectionPanelNode: ASDisplayNode {
private let context: AccountContext
private let peerId: PeerId
@ -589,6 +457,7 @@ private final class PeerInfoInteraction {
let updateBio: (String) -> Void
let openDeletePeer: () -> Void
let openFaq: (String?) -> Void
let openAddMember: () -> Void
init(
openUsername: @escaping (String) -> Void,
@ -628,7 +497,8 @@ private final class PeerInfoInteraction {
accountContextMenu: @escaping (AccountRecordId, ASDisplayNode, ContextGesture?) -> Void,
updateBio: @escaping (String) -> Void,
openDeletePeer: @escaping () -> Void,
openFaq: @escaping (String?) -> Void
openFaq: @escaping (String?) -> Void,
openAddMember: @escaping () -> Void
) {
self.openUsername = openUsername
self.openPhone = openPhone
@ -668,6 +538,7 @@ private final class PeerInfoInteraction {
self.updateBio = updateBio
self.openDeletePeer = openDeletePeer
self.openFaq = openFaq
self.openAddMember = openAddMember
}
}
@ -1161,6 +1032,34 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese
}
if let peer = data.peer, let members = data.members, case let .shortList(_, memberList) = members {
var canAddMembers = false
if let group = data.peer as? TelegramGroup {
switch group.role {
case .admin, .creator:
canAddMembers = true
case .member:
break
}
if !group.hasBannedPermission(.banAddMembers) {
canAddMembers = true
}
} else if let channel = data.peer as? TelegramChannel {
switch channel.info {
case .broadcast:
break
case .group:
if channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) {
canAddMembers = true
}
}
}
if canAddMembers {
items[.peerMembers]!.append(PeerInfoScreenActionItem(id: 0, text: presentationData.strings.PeerInfo_ButtonAddMember, color: .accent, icon: UIImage(bundleImageName: "Contact List/AddMemberIcon"), alignment: .peerList, action: {
interaction.openAddMember()
}))
}
for member in memberList {
let isAccountPeer = member.id == context.account.peerId
items[.peerMembers]!.append(PeerInfoScreenMemberItem(id: member.id, context: context, enclosingPeer: peer, member: member, action: isAccountPeer ? nil : { action in
@ -1543,8 +1442,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
fileprivate let cachedDataPromise = Promise<CachedPeerData?>()
let scrollNode: ASScrollNode
private let leftOverlayNode: ASDisplayNode
private let rightOverlayNode: ASDisplayNode
let headerNode: PeerInfoHeaderNode
private var regularSections: [AnyHashable: PeerInfoScreenItemSectionContainerNode] = [:]
@ -1641,11 +1538,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
self.scrollNode.view.delaysContentTouches = false
self.scrollNode.canCancelAllTouchesInViews = true
self.leftOverlayNode = ASDisplayNode()
self.leftOverlayNode.isUserInteractionEnabled = false
self.rightOverlayNode = ASDisplayNode()
self.rightOverlayNode.isUserInteractionEnabled = false
self.headerNode = PeerInfoHeaderNode(context: context, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, isSettings: isSettings)
self.paneContainerNode = PeerInfoPaneContainerNode(context: context, updatedPresentationData: controller.updatedPresentationData, peerId: peerId, isMediaOnly: self.isMediaOnly)
@ -1653,10 +1545,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
self.paneContainerNode.parentController = controller
self.headerNode.updateHeaderAlpha = { [weak self] alpha, transition in
self?.updateHeaderBackgroundAlpha(alpha, transition: transition)
}
self._interaction = PeerInfoInteraction(
openUsername: { [weak self] value in
self?.openUsername(value: value)
@ -1771,6 +1659,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
},
openFaq: { [weak self] anchor in
self?.openFaq(anchor: anchor)
},
openAddMember: { [weak self] in
self?.openAddMember()
}
)
@ -2283,13 +2174,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
self.addSubnode(self.scrollNode)
self.scrollNode.addSubnode(self.paneContainerNode)
self.leftOverlayNode.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
self.rightOverlayNode.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
self.addSubnode(self.leftOverlayNode)
self.addSubnode(self.rightOverlayNode)
self.addSubnode(self.headerNode.buttonsContainerNode)
self.addSubnode(self.headerNode)
self.scrollNode.view.isScrollEnabled = !self.isMediaOnly
@ -2380,6 +2265,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
}
self.paneContainerNode.openAddMemberAction = { [weak self] in
guard let strongSelf = self else {
return
}
strongSelf.openAddMember()
}
self.paneContainerNode.requestPerformPeerMemberAction = { [weak self] member, action in
guard let strongSelf = self else {
return
@ -2996,11 +2888,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
override func didLoad() {
super.didLoad()
if self.isSettings {
self.updateHeaderBackgroundAlpha(0.0, transition: .immediate)
}
self.view.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in
if let strongSelf = self {
return strongSelf.state.isEditing
@ -3009,15 +2897,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
}
}
public func updateHeaderBackgroundAlpha(_ alpha: CGFloat, transition: ContainedViewLayoutTransition) {
self.controller?.navigationBar?.updateBackgroundAlpha(alpha, transition: transition)
transition.updateAlpha(node: self.headerNode.backgroundNode, alpha: alpha, delay: 0.15)
transition.updateAlpha(node: self.headerNode.expandedBackgroundNode, alpha: alpha, delay: 0.15)
transition.updateAlpha(node: self.headerNode.separatorNode, alpha: alpha, delay: 0.15)
}
var canAttachVideo: Bool?
private func updateData(_ data: PeerInfoScreenData) {
@ -3613,7 +3493,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
return .single(items)
}
let allHeaderButtons = Set(peerInfoHeaderButtons(peer: peer, cachedData: data.cachedData, isOpenedFromChat: strongSelf.isOpenedFromChat, isExpanded: false, videoCallsEnabled: strongSelf.videoCallsEnabled, isSecretChat: strongSelf.peerId.namespace == Namespaces.Peer.SecretChat, isContact: strongSelf.data?.isContact ?? false))
let allHeaderButtons = Set(peerInfoHeaderButtons(peer: peer, cachedData: data.cachedData, isOpenedFromChat: strongSelf.isOpenedFromChat, isExpanded: true, videoCallsEnabled: strongSelf.videoCallsEnabled, isSecretChat: strongSelf.peerId.namespace == Namespaces.Peer.SecretChat, isContact: strongSelf.data?.isContact ?? false))
let headerButtons = Set(peerInfoHeaderButtons(peer: peer, cachedData: data.cachedData, isOpenedFromChat: strongSelf.isOpenedFromChat, isExpanded: strongSelf.headerNode.isAvatarExpanded, videoCallsEnabled: strongSelf.videoCallsEnabled, isSecretChat: strongSelf.peerId.namespace == Namespaces.Peer.SecretChat, isContact: strongSelf.data?.isContact ?? false))
let filteredButtons = allHeaderButtons.subtracting(headerButtons)
@ -6356,9 +6236,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
self.presentationData = presentationData
self.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
self.leftOverlayNode.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
self.rightOverlayNode.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
self.updateNavigationExpansionPresentation(isExpanded: self.headerNode.isAvatarExpanded, animated: false)
if let (layout, navigationHeight) = self.validLayout {
@ -6395,14 +6273,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} else {
sectionInset = 0.0
}
let headerInset: CGFloat
if self.isSettings {
headerInset = sectionInset
} else {
headerInset = layout.safeInsets.left
}
let headerInset = sectionInset
let headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : self.scrollNode.view.contentOffset.y, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, transition: transition, additive: additive)
var headerHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : self.scrollNode.view.contentOffset.y, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, transition: transition, additive: additive)
if !self.isSettings && !self.state.isEditing {
headerHeight += 71.0
}
let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight))
if additive {
transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame)
@ -6413,20 +6289,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
contentHeight += navigationHeight
}
var currentInsets = UIEdgeInsets()
var validRegularSections: [AnyHashable] = []
if !self.isMediaOnly {
var insets = UIEdgeInsets()
if self.isSettings {
insets.left += sectionInset
insets.right += sectionInset
} else {
insets = layout.safeInsets
}
if !self.state.isEditing {
currentInsets = insets
}
insets.left += sectionInset
insets.right += sectionInset
let items = self.isSettings ? settingsItems(data: self.data, context: self.context, presentationData: self.presentationData, interaction: self.interaction, isExpanded: self.headerNode.isAvatarExpanded) : infoItems(data: self.data, context: self.context, presentationData: self.presentationData, interaction: self.interaction, nearbyPeerDistance: self.nearbyPeerDistance, callMessages: self.callMessages)
@ -6453,9 +6320,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
sectionNode.alpha = 0.0
transition.updateAlpha(node: sectionNode, alpha: 1.0, delay: 0.1)
}
let sectionHeight = sectionNode.update(width: layout.size.width, safeInsets: insets, presentationData: self.presentationData, items: sectionItems, transition: transition)
let sectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: sectionHeight))
let sectionWidth = layout.size.width - insets.left - insets.right
let sectionHeight = sectionNode.update(width: sectionWidth, safeInsets: UIEdgeInsets(), hasCorners: !insets.left.isZero, presentationData: self.presentationData, items: sectionItems, transition: transition)
let sectionFrame = CGRect(origin: CGPoint(x: insets.left, y: contentHeight), size: CGSize(width: sectionWidth, height: sectionHeight))
if additive {
transition.updateFrameAdditive(node: sectionNode, frame: sectionFrame)
} else {
@ -6500,10 +6368,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
var insets = UIEdgeInsets()
insets.left += sectionInset
insets.right += sectionInset
if self.state.isEditing {
currentInsets = insets
}
validEditingSections.append(sectionId)
@ -6517,9 +6381,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
self.editingSections[sectionId] = sectionNode
self.scrollNode.addSubnode(sectionNode)
}
let sectionHeight = sectionNode.update(width: layout.size.width, safeInsets: insets, presentationData: self.presentationData, items: sectionItems, transition: transition)
let sectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: sectionHeight))
let sectionWidth = layout.size.width - insets.left - insets.right
let sectionHeight = sectionNode.update(width: sectionWidth, safeInsets: UIEdgeInsets(), hasCorners: !insets.left.isZero, presentationData: self.presentationData, items: sectionItems, transition: transition)
let sectionFrame = CGRect(origin: CGPoint(x: insets.left, y: contentHeight), size: CGSize(width: sectionWidth, height: sectionHeight))
if wasAdded {
sectionNode.frame = sectionFrame
@ -6636,7 +6501,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
if self.isSettings {
contentHeight = max(contentHeight, layout.size.height + 140.0 + (self.headerNode.twoLineInfo ? 17.0 : 0.0) - layout.intrinsicInsets.bottom)
contentHeight = max(contentHeight, layout.size.height + 140.0 - layout.intrinsicInsets.bottom)
}
self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: contentHeight)
if self.isSettings {
@ -6645,17 +6510,13 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
if let restoreContentOffset = restoreContentOffset {
self.scrollNode.view.contentOffset = restoreContentOffset
}
let relativeHeaderFrame = self.headerNode.view.convert(self.headerNode.bounds, to: self.view)
transition.updateFrame(node: self.leftOverlayNode, frame: CGRect(x: 0.0, y: relativeHeaderFrame.maxY + UIScreenPixel - self.scrollNode.view.contentOffset.y, width: currentInsets.left, height: layout.size.height * 10.0))
transition.updateFrame(node: self.rightOverlayNode, frame: CGRect(x: layout.size.width - currentInsets.right, y: relativeHeaderFrame.maxY + UIScreenPixel - self.scrollNode.view.contentOffset.y, width: currentInsets.right, height: layout.size.height * 10.0))
if additive {
transition.updateFrameAdditive(node: self.paneContainerNode, frame: paneContainerFrame)
} else {
transition.updateFrame(node: self.paneContainerNode, frame: paneContainerFrame)
}
self.ignoreScrolling = false
self.updateNavigation(transition: transition, additive: additive)
@ -6707,13 +6568,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
} else {
sectionInset = 0.0
}
let headerInset: CGFloat
if self.isSettings {
headerInset = sectionInset
} else {
headerInset = layout.safeInsets.left
}
let headerInset = sectionInset
let _ = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: navigationHeight, isModalOverlay: layout.isModalOverlay, isMediaOnly: self.isMediaOnly, contentOffset: self.isMediaOnly ? 212.0 : offsetY, paneContainerY: self.paneContainerNode.frame.minY, presentationData: self.presentationData, peer: self.data?.peer, cachedData: self.data?.cachedData, notificationSettings: self.data?.notificationSettings, statusData: self.data?.status, panelStatusData: self.customStatusData, isSecretChat: self.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.data?.isContact ?? false, isSettings: self.isSettings, state: self.state, transition: transition, additive: additive)
}
@ -6731,10 +6587,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance
}
if !self.isSettings {
transition.updateAlpha(node: self.headerNode.separatorNode, alpha: 1.0 - effectiveAreaExpansionFraction)
}
let visibleHeight = self.scrollNode.view.contentOffset.y + self.scrollNode.view.bounds.height - self.paneContainerNode.frame.minY
var bottomInset = layout.intrinsicInsets.bottom
@ -6797,18 +6649,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
private var canOpenAvatarByDragging = false
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if self.ignoreScrolling {
guard !self.ignoreScrolling else {
return
}
let headerFrame = self.headerNode.view.convert(self.headerNode.bounds, to: self.view)
if !self.headerNode.isAvatarExpanded {
self.leftOverlayNode.layer.removeAllAnimations()
self.rightOverlayNode.layer.removeAllAnimations()
}
self.leftOverlayNode.frame = CGRect(x: 0.0, y: headerFrame.maxY + UIScreenPixel - scrollView.contentOffset.y, width: self.leftOverlayNode.frame.width, height: self.leftOverlayNode.frame.height)
self.rightOverlayNode.frame = CGRect(x: self.rightOverlayNode.frame.minX, y: headerFrame.maxY + UIScreenPixel - scrollView.contentOffset.y, width: self.rightOverlayNode.frame.width, height: self.rightOverlayNode.frame.height)
if !self.state.isEditing {
if self.canAddVelocity {
self.previousVelocityM1 = self.previousVelocity
@ -6938,10 +6782,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}
}
} else {
var height: CGFloat = self.isSettings ? 140.0 : 212.0
if self.headerNode.twoLineInfo {
height += 17.0
}
let height: CGFloat = self.isSettings ? 140.0 : 140.0
if targetContentOffset.pointee.y < height {
if targetContentOffset.pointee.y < height / 2.0 {
targetContentOffset.pointee.y = 0.0
@ -7618,12 +7459,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
} else {
sectionInset = 0.0
}
let headerInset: CGFloat
if screenNode.isSettings {
headerInset = sectionInset
} else {
headerInset = layout.safeInsets.left
}
let headerInset = sectionInset
topHeight = self.headerNode.update(width: layout.size.width, containerHeight: layout.size.height, containerInset: headerInset, statusBarHeight: layout.statusBarHeight ?? 0.0, navigationHeight: topNavigationBar.bounds.height, isModalOverlay: layout.isModalOverlay, isMediaOnly: false, contentOffset: 0.0, paneContainerY: 0.0, presentationData: self.presentationData, peer: self.screenNode.data?.peer, cachedData: self.screenNode.data?.cachedData, notificationSettings: self.screenNode.data?.notificationSettings, statusData: self.screenNode.data?.status, panelStatusData: nil, isSecretChat: self.screenNode.peerId.namespace == Namespaces.Peer.SecretChat, isContact: self.screenNode.data?.isContact ?? false, isSettings: self.screenNode.isSettings, state: self.screenNode.state, transition: transition, additive: false)
}

View File

@ -50,7 +50,7 @@ private final class PeerInfoScreenMultilineInputItemNode: PeerInfoScreenItemNode
self.addSubnode(self.bottomSeparatorNode)
}
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, transition: ContainedViewLayoutTransition) -> CGFloat {
override func update(width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool, transition: ContainedViewLayoutTransition) -> CGFloat {
guard let item = item as? PeerInfoScreenMultilineInputItem else {
return 10.0
}
@ -101,7 +101,7 @@ private final class PeerInfoScreenMultilineInputItemNode: PeerInfoScreenItemNode
separatorInset += 49.0
}
let hasCorners = safeInsets.left > 0.0 && (topItem == nil || bottomItem == nil)
let hasCorners = hasCorners && (topItem == nil || bottomItem == nil)
let hasTopCorners = hasCorners && topItem == nil
let hasBottomCorners = hasCorners && bottomItem == nil