mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-08 08:31:13 +00:00
Peer profile improvements
This commit is contained in:
parent
abfc1b54e5
commit
493fd5347d
@ -485,7 +485,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
strongSelf.tabContainerNode.cancelAnimations()
|
strongSelf.tabContainerNode.cancelAnimations()
|
||||||
strongSelf.chatListDisplayNode.inlineTabContainerNode.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)
|
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()
|
self.reloadFilters()
|
||||||
@ -549,7 +549,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
|
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
|
||||||
|
|
||||||
if let layout = self.validLayout {
|
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)
|
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
|
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)))
|
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 {
|
if let tabContainerData = self.tabContainerData {
|
||||||
self.chatListDisplayNode.inlineTabContainerNode.isHidden = !tabContainerData.1 || tabContainerData.0.count <= 1
|
self.chatListDisplayNode.inlineTabContainerNode.isHidden = !tabContainerData.1 || tabContainerData.0.count <= 1
|
||||||
} else {
|
} else {
|
||||||
@ -1621,7 +1621,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
strongSelf.containerLayoutUpdated(layout, transition: transition)
|
strongSelf.containerLayoutUpdated(layout, transition: transition)
|
||||||
(strongSelf.parent as? TabBarController)?.updateLayout(transition: transition)
|
(strongSelf.parent as? TabBarController)?.updateLayout(transition: transition)
|
||||||
} else {
|
} 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))
|
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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,6 +83,7 @@ private final class ItemNode: ASDisplayNode {
|
|||||||
private(set) var unreadCount: Int = 0
|
private(set) var unreadCount: Int = 0
|
||||||
|
|
||||||
private var isReordering: Bool = false
|
private var isReordering: Bool = false
|
||||||
|
private var isEditing: Bool = false
|
||||||
|
|
||||||
private var theme: PresentationTheme?
|
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) {
|
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 {
|
if self.theme !== presentationData.theme {
|
||||||
self.theme = presentationData.theme
|
self.theme = presentationData.theme
|
||||||
|
|
||||||
@ -212,7 +215,7 @@ private final class ItemNode: ASDisplayNode {
|
|||||||
self.selectionFraction = selectionFraction
|
self.selectionFraction = selectionFraction
|
||||||
self.unreadCount = unreadCount
|
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 isReordering && !isAllChats {
|
||||||
if self.deleteButtonNode == nil {
|
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 selectionAlpha: CGFloat = selectionFraction * selectionFraction
|
||||||
let deselectionAlpha: CGFloat = 1.0// - 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)
|
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
|
let width: CGFloat
|
||||||
if self.unreadCount == 0 || self.isReordering {
|
if self.unreadCount == 0 || self.isReordering || self.isEditing {
|
||||||
if !self.isReordering {
|
if !self.isReordering {
|
||||||
self.badgeContainerNode.alpha = 0.0
|
self.badgeContainerNode.alpha = 0.0
|
||||||
}
|
}
|
||||||
@ -636,6 +639,11 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
|
|||||||
let isFirstTime = self.currentParams == nil
|
let isFirstTime = self.currentParams == nil
|
||||||
let transition: ContainedViewLayoutTransition = isFirstTime ? .immediate : proposedTransition
|
let transition: ContainedViewLayoutTransition = isFirstTime ? .immediate : proposedTransition
|
||||||
|
|
||||||
|
var isEditing = isEditing
|
||||||
|
if isReordering {
|
||||||
|
isEditing = false
|
||||||
|
}
|
||||||
|
|
||||||
var focusOnSelectedFilter = self.currentParams?.selectedFilter != selectedFilter
|
var focusOnSelectedFilter = self.currentParams?.selectedFilter != selectedFilter
|
||||||
let previousScrollBounds = self.scrollNode.bounds
|
let previousScrollBounds = self.scrollNode.bounds
|
||||||
let previousContentWidth = self.scrollNode.view.contentSize.width
|
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.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))
|
transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
|
|
||||||
@ -754,7 +762,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
|
|||||||
selectionFraction = 0.0
|
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] = []
|
var removeKeys: [ChatListFilterTabEntryId] = []
|
||||||
for (id, _) in self.itemNodes {
|
for (id, _) in self.itemNodes {
|
||||||
|
@ -162,7 +162,6 @@ public final class InviteLinkQRCodeController: ViewController {
|
|||||||
private let backgroundNode: ASDisplayNode
|
private let backgroundNode: ASDisplayNode
|
||||||
private let contentBackgroundNode: ASDisplayNode
|
private let contentBackgroundNode: ASDisplayNode
|
||||||
private let titleNode: ASTextNode
|
private let titleNode: ASTextNode
|
||||||
private let subtitleNode: ASTextNode
|
|
||||||
private let cancelButton: HighlightableButtonNode
|
private let cancelButton: HighlightableButtonNode
|
||||||
|
|
||||||
private let textNode: ImmediateTextNode
|
private let textNode: ImmediateTextNode
|
||||||
@ -209,9 +208,6 @@ public final class InviteLinkQRCodeController: ViewController {
|
|||||||
self.titleNode = ASTextNode()
|
self.titleNode = ASTextNode()
|
||||||
self.titleNode.attributedText = NSAttributedString(string: self.presentationData.strings.InviteLink_QRCode_Title, font: Font.bold(17.0), textColor: textColor)
|
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 = HighlightableButtonNode()
|
||||||
self.cancelButton.setTitle(self.presentationData.strings.Common_Done, with: Font.bold(17.0), with: accentColor, for: .normal)
|
self.cancelButton.setTitle(self.presentationData.strings.Common_Done, with: Font.bold(17.0), with: accentColor, for: .normal)
|
||||||
|
|
||||||
@ -255,9 +251,7 @@ public final class InviteLinkQRCodeController: ViewController {
|
|||||||
self.contentContainerNode.addSubnode(self.qrIconNode)
|
self.contentContainerNode.addSubnode(self.qrIconNode)
|
||||||
self.contentContainerNode.addSubnode(self.qrButtonNode)
|
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: Font.regular(13.0), textColor: secondaryTextColor)
|
||||||
|
|
||||||
self.textNode.attributedText = NSAttributedString(string: isGroup ? self.presentationData.strings.InviteLink_QRCode_Info : self.presentationData.strings.InviteLink_QRCode_InfoChannel, font: textFont, textColor: secondaryTextColor)
|
|
||||||
self.buttonNode.title = self.presentationData.strings.InviteLink_QRCode_Share
|
self.buttonNode.title = self.presentationData.strings.InviteLink_QRCode_Share
|
||||||
|
|
||||||
self.cancelButton.addTarget(self, action: #selector(self.cancelButtonPressed), forControlEvents: .touchUpInside)
|
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.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.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 {
|
if previousTheme !== presentationData.theme, let (layout, navigationBarHeight) = self.containerLayout {
|
||||||
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate)
|
||||||
|
@ -9,6 +9,7 @@ import PresentationDataUtils
|
|||||||
|
|
||||||
public enum ItemListPeerActionItemHeight {
|
public enum ItemListPeerActionItemHeight {
|
||||||
case generic
|
case generic
|
||||||
|
case compactPeerList
|
||||||
case peerList
|
case peerList
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +174,10 @@ class ItemListPeerActionItemNode: ListViewItemNode {
|
|||||||
verticalInset = 14.0
|
verticalInset = 14.0
|
||||||
verticalOffset = 0.0
|
verticalOffset = 0.0
|
||||||
leftInset = 65.0 + params.leftInset
|
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)
|
let editingOffset: CGFloat = (item.editing ? 38.0 : 0.0)
|
||||||
|
@ -10,6 +10,7 @@ enum PeerInfoScreenActionColor {
|
|||||||
enum PeerInfoScreenActionAligmnent {
|
enum PeerInfoScreenActionAligmnent {
|
||||||
case natural
|
case natural
|
||||||
case center
|
case center
|
||||||
|
case peerList
|
||||||
}
|
}
|
||||||
|
|
||||||
final class PeerInfoScreenActionItem: PeerInfoScreenItem {
|
final class PeerInfoScreenActionItem: PeerInfoScreenItem {
|
||||||
@ -78,7 +79,7 @@ private final class PeerInfoScreenActionItemNode: PeerInfoScreenItemNode {
|
|||||||
self.addSubnode(self.activateArea)
|
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 {
|
guard let item = item as? PeerInfoScreenActionItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
@ -88,7 +89,10 @@ private final class PeerInfoScreenActionItemNode: PeerInfoScreenItemNode {
|
|||||||
self.selectionNode.pressed = item.action
|
self.selectionNode.pressed = item.action
|
||||||
|
|
||||||
let sideInset: CGFloat = 16.0 + safeInsets.left
|
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 rightInset = sideInset
|
||||||
let separatorInset = item.icon == nil ? sideInset : leftInset - 1.0
|
let separatorInset = item.icon == nil ? sideInset : leftInset - 1.0
|
||||||
let titleFont = Font.regular(presentationData.listsFontSize.itemListBaseFontSize)
|
let titleFont = Font.regular(presentationData.listsFontSize.itemListBaseFontSize)
|
||||||
@ -131,7 +135,7 @@ private final class PeerInfoScreenActionItemNode: PeerInfoScreenItemNode {
|
|||||||
transition.updateFrame(node: self.textNode, frame: textFrame)
|
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 hasTopCorners = hasCorners && topItem == nil
|
||||||
let hasBottomCorners = hasCorners && bottomItem == nil
|
let hasBottomCorners = hasCorners && bottomItem == nil
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ final class PeerInfoScreenAddressItem: PeerInfoScreenItem {
|
|||||||
private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
|
private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
|
||||||
private let selectionNode: PeerInfoScreenSelectableBackgroundNode
|
private let selectionNode: PeerInfoScreenSelectableBackgroundNode
|
||||||
private let bottomSeparatorNode: ASDisplayNode
|
private let bottomSeparatorNode: ASDisplayNode
|
||||||
|
private let maskNode: ASImageNode
|
||||||
|
|
||||||
private var item: PeerInfoScreenAddressItem?
|
private var item: PeerInfoScreenAddressItem?
|
||||||
private var itemNode: ItemListAddressItemNode?
|
private var itemNode: ItemListAddressItemNode?
|
||||||
@ -53,6 +54,9 @@ private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
|
|||||||
self.bottomSeparatorNode = ASDisplayNode()
|
self.bottomSeparatorNode = ASDisplayNode()
|
||||||
self.bottomSeparatorNode.isLayerBacked = true
|
self.bottomSeparatorNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.maskNode = ASImageNode()
|
||||||
|
self.maskNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
bringToFrontForHighlightImpl = { [weak self] in
|
bringToFrontForHighlightImpl = { [weak self] in
|
||||||
@ -61,9 +65,10 @@ private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
|
|||||||
|
|
||||||
self.addSubnode(self.bottomSeparatorNode)
|
self.addSubnode(self.bottomSeparatorNode)
|
||||||
self.addSubnode(self.selectionNode)
|
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 {
|
guard let item = item as? PeerInfoScreenAddressItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
@ -108,6 +113,14 @@ private final class PeerInfoScreenAddressItemNode: PeerInfoScreenItemNode {
|
|||||||
|
|
||||||
let height = itemNode.contentSize.height
|
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))
|
transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(), size: itemNode.bounds.size))
|
||||||
|
|
||||||
let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel
|
let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel
|
||||||
|
@ -52,7 +52,7 @@ private final class PeerInfoScreenCallListItemNode: PeerInfoScreenItemNode {
|
|||||||
self.addSubnode(self.selectionNode)
|
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 {
|
guard let item = item as? PeerInfoScreenCallListItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ private final class PeerInfoScreenCommentItemNode: PeerInfoScreenItemNode {
|
|||||||
self.addSubnode(self.activateArea)
|
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 {
|
guard let item = item as? PeerInfoScreenCommentItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ private final class PeerInfoScreenDisclosureEncryptionKeyItemNode: PeerInfoScree
|
|||||||
private let keyNode: ASImageNode
|
private let keyNode: ASImageNode
|
||||||
private let arrowNode: ASImageNode
|
private let arrowNode: ASImageNode
|
||||||
private let bottomSeparatorNode: ASDisplayNode
|
private let bottomSeparatorNode: ASDisplayNode
|
||||||
|
private let maskNode: ASImageNode
|
||||||
|
|
||||||
private var item: PeerInfoScreenDisclosureEncryptionKeyItem?
|
private var item: PeerInfoScreenDisclosureEncryptionKeyItem?
|
||||||
|
|
||||||
@ -53,6 +54,9 @@ private final class PeerInfoScreenDisclosureEncryptionKeyItemNode: PeerInfoScree
|
|||||||
self.bottomSeparatorNode = ASDisplayNode()
|
self.bottomSeparatorNode = ASDisplayNode()
|
||||||
self.bottomSeparatorNode.isLayerBacked = true
|
self.bottomSeparatorNode.isLayerBacked = true
|
||||||
|
|
||||||
|
self.maskNode = ASImageNode()
|
||||||
|
self.maskNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
bringToFrontForHighlightImpl = { [weak self] in
|
bringToFrontForHighlightImpl = { [weak self] in
|
||||||
@ -64,9 +68,10 @@ private final class PeerInfoScreenDisclosureEncryptionKeyItemNode: PeerInfoScree
|
|||||||
self.addSubnode(self.textNode)
|
self.addSubnode(self.textNode)
|
||||||
self.addSubnode(self.keyNode)
|
self.addSubnode(self.keyNode)
|
||||||
self.addSubnode(self.arrowNode)
|
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 {
|
guard let item = item as? PeerInfoScreenDisclosureEncryptionKeyItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
@ -106,6 +111,14 @@ private final class PeerInfoScreenDisclosureEncryptionKeyItemNode: PeerInfoScree
|
|||||||
|
|
||||||
transition.updateFrame(node: self.textNode, frame: textFrame)
|
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
|
let highlightNodeOffset: CGFloat = topItem == nil ? 0.0 : UIScreenPixel
|
||||||
self.selectionNode.update(size: CGSize(width: width, height: height + highlightNodeOffset), theme: presentationData.theme, transition: transition)
|
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)))
|
transition.updateFrame(node: self.selectionNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -highlightNodeOffset), size: CGSize(width: width, height: height + highlightNodeOffset)))
|
||||||
|
@ -109,7 +109,7 @@ private final class PeerInfoScreenDisclosureItemNode: PeerInfoScreenItemNode {
|
|||||||
self.addSubnode(self.activateArea)
|
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 {
|
guard let item = item as? PeerInfoScreenDisclosureItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ private final class PeerInfoScreenDisclosureItemNode: PeerInfoScreenItemNode {
|
|||||||
transition.updateFrame(node: self.labelNode, frame: labelFrame)
|
transition.updateFrame(node: self.labelNode, frame: labelFrame)
|
||||||
transition.updateFrame(node: self.textNode, frame: textFrame)
|
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 hasTopCorners = hasCorners && topItem == nil
|
||||||
let hasBottomCorners = hasCorners && bottomItem == nil
|
let hasBottomCorners = hasCorners && bottomItem == nil
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ private final class PeerInfoScreenHeaderItemNode: PeerInfoScreenItemNode {
|
|||||||
self.addSubnode(self.activateArea)
|
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 {
|
guard let item = item as? PeerInfoScreenHeaderItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ private final class PeerInfoScreenInfoItemNode: PeerInfoScreenItemNode {
|
|||||||
self.addSubnode(self.bottomSeparatorNode)
|
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 {
|
guard let item = item as? PeerInfoScreenInfoItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ private final class PeerInfoScreenInfoItemNode: PeerInfoScreenItemNode {
|
|||||||
separatorInset += 49.0
|
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 hasTopCorners = hasCorners && topItem == nil
|
||||||
let hasBottomCorners = hasCorners && bottomItem == nil
|
let hasBottomCorners = hasCorners && bottomItem == nil
|
||||||
|
|
||||||
|
@ -54,6 +54,7 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem {
|
|||||||
|
|
||||||
private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
|
private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
|
||||||
private let selectionNode: PeerInfoScreenSelectableBackgroundNode
|
private let selectionNode: PeerInfoScreenSelectableBackgroundNode
|
||||||
|
private let maskNode: ASImageNode
|
||||||
private let labelNode: ImmediateTextNode
|
private let labelNode: ImmediateTextNode
|
||||||
private let textNode: ImmediateTextNode
|
private let textNode: ImmediateTextNode
|
||||||
private let bottomSeparatorNode: ASDisplayNode
|
private let bottomSeparatorNode: ASDisplayNode
|
||||||
@ -75,6 +76,9 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
|
|||||||
self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() })
|
self.selectionNode = PeerInfoScreenSelectableBackgroundNode(bringToFrontForHighlight: { bringToFrontForHighlightImpl?() })
|
||||||
self.selectionNode.isUserInteractionEnabled = false
|
self.selectionNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
|
self.maskNode = ASImageNode()
|
||||||
|
self.maskNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
self.labelNode = ImmediateTextNode()
|
self.labelNode = ImmediateTextNode()
|
||||||
self.labelNode.displaysAsynchronously = false
|
self.labelNode.displaysAsynchronously = false
|
||||||
self.labelNode.isUserInteractionEnabled = false
|
self.labelNode.isUserInteractionEnabled = false
|
||||||
@ -102,6 +106,7 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode {
|
|||||||
|
|
||||||
self.addSubnode(self.bottomSeparatorNode)
|
self.addSubnode(self.bottomSeparatorNode)
|
||||||
self.addSubnode(self.selectionNode)
|
self.addSubnode(self.selectionNode)
|
||||||
|
self.addSubnode(self.maskNode)
|
||||||
self.addSubnode(self.labelNode)
|
self.addSubnode(self.labelNode)
|
||||||
self.addSubnode(self.textNode)
|
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 {
|
guard let item = item as? PeerInfoScreenLabeledValueItem else {
|
||||||
return 10.0
|
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.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)
|
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.frame = CGRect(origin: CGPoint(), size: CGSize(width: width, height: height))
|
||||||
self.activateArea.accessibilityLabel = item.label
|
self.activateArea.accessibilityLabel = item.label
|
||||||
|
@ -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 {
|
guard let item = item as? PeerInfoScreenMemberItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
@ -226,7 +226,7 @@ private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode {
|
|||||||
transition.updateFrame(node: itemNode, frame: CGRect(origin: CGPoint(), size: itemNode.bounds.size))
|
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 hasTopCorners = hasCorners && topItem == nil
|
||||||
let hasBottomCorners = hasCorners && bottomItem == nil
|
let hasBottomCorners = hasCorners && bottomItem == nil
|
||||||
|
|
||||||
|
@ -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 {
|
guard let item = item as? PeerInfoScreenSwitchItem else {
|
||||||
return 10.0
|
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 hasTopCorners = hasCorners && topItem == nil
|
||||||
let hasBottomCorners = hasCorners && bottomItem == nil
|
let hasBottomCorners = hasCorners && bottomItem == nil
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import ContextUI
|
|||||||
import PhotoResources
|
import PhotoResources
|
||||||
import TelegramUIPreferences
|
import TelegramUIPreferences
|
||||||
import ItemListPeerItem
|
import ItemListPeerItem
|
||||||
|
import ItemListPeerActionItem
|
||||||
import MergeLists
|
import MergeLists
|
||||||
import ItemListUI
|
import ItemListUI
|
||||||
|
|
||||||
@ -26,25 +27,67 @@ enum PeerMembersListAction {
|
|||||||
case remove
|
case remove
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct PeerMembersListEntry: Comparable, Identifiable {
|
private enum PeerMembersListEntryStableId: Hashable {
|
||||||
let theme: PresentationTheme
|
case addMember
|
||||||
let index: Int
|
case peer(PeerId)
|
||||||
let member: PeerInfoMember
|
}
|
||||||
|
|
||||||
var stableId: PeerId {
|
private enum PeerMembersListEntry: Comparable, Identifiable {
|
||||||
return self.member.id
|
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 {
|
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 {
|
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 {
|
func item(context: AccountContext, presentationData: PresentationData, enclosingPeer: Peer, addMemberAction: @escaping () -> Void, action: @escaping (PeerInfoMember, PeerMembersListAction) -> Void) -> ListViewItem {
|
||||||
let member = self.member
|
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?
|
let label: String?
|
||||||
if let rank = member.rank {
|
if let rank = member.rank {
|
||||||
label = rank
|
label = rank
|
||||||
@ -87,13 +130,14 @@ private struct PeerMembersListEntry: Comparable, Identifiable {
|
|||||||
}*/, hasTopStripe: false, noInsets: true, disableInteractiveTransitionIfNecessary: true)
|
}*/, 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 (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||||
|
|
||||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
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 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, 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)
|
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 {
|
final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let membersContext: PeerInfoMembersContext
|
private let membersContext: PeerInfoMembersContext
|
||||||
|
private let addMemberAction: () -> Void
|
||||||
private let action: (PeerInfoMember, PeerMembersListAction) -> Void
|
private let action: (PeerInfoMember, PeerMembersListAction) -> Void
|
||||||
|
|
||||||
weak var parentController: ViewController?
|
weak var parentController: ViewController?
|
||||||
@ -132,9 +177,10 @@ final class PeerInfoMembersPaneNode: ASDisplayNode, PeerInfoPaneNode {
|
|||||||
|
|
||||||
private var disposable: Disposable?
|
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.context = context
|
||||||
self.membersContext = membersContext
|
self.membersContext = membersContext
|
||||||
|
self.addMemberAction = addMemberAction
|
||||||
self.action = action
|
self.action = action
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
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) {
|
private func updateState(enclosingPeer: Peer, state: PeerInfoMembersState, presentationData: PresentationData) {
|
||||||
var entries: [PeerMembersListEntry] = []
|
var entries: [PeerMembersListEntry] = []
|
||||||
for member in state.members {
|
if state.canAddMembers {
|
||||||
entries.append(PeerMembersListEntry(theme: presentationData.theme, index: entries.count, member: member))
|
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?.action(member, action)
|
||||||
})
|
})
|
||||||
self.enclosingPeer = enclosingPeer
|
self.enclosingPeer = enclosingPeer
|
||||||
|
@ -1066,9 +1066,6 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
|
|||||||
hasDiscussion = true
|
hasDiscussion = true
|
||||||
}
|
}
|
||||||
case .group:
|
case .group:
|
||||||
if channel.flags.contains(.isCreator) || channel.hasPermission(.inviteMembers) {
|
|
||||||
result.append(.addMember)
|
|
||||||
}
|
|
||||||
if channel.flags.contains(.hasVoiceChat) {
|
if channel.flags.contains(.hasVoiceChat) {
|
||||||
hasVoiceChat = true
|
hasVoiceChat = true
|
||||||
}
|
}
|
||||||
@ -1082,10 +1079,10 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
|
|||||||
default:
|
default:
|
||||||
displayLeave = false
|
displayLeave = false
|
||||||
}
|
}
|
||||||
result.append(.mute)
|
|
||||||
if hasVoiceChat || canStartVoiceChat {
|
if hasVoiceChat || canStartVoiceChat {
|
||||||
result.append(.voiceChat)
|
result.append(.voiceChat)
|
||||||
}
|
}
|
||||||
|
result.append(.mute)
|
||||||
if hasDiscussion {
|
if hasDiscussion {
|
||||||
result.append(.discussion)
|
result.append(.discussion)
|
||||||
}
|
}
|
||||||
@ -1104,7 +1101,6 @@ func peerInfoHeaderButtons(peer: Peer?, cachedData: CachedPeerData?, isOpenedFro
|
|||||||
result.append(.more)
|
result.append(.more)
|
||||||
}
|
}
|
||||||
} else if let group = peer as? TelegramGroup {
|
} else if let group = peer as? TelegramGroup {
|
||||||
var canAddMembers = false
|
|
||||||
var hasVoiceChat = false
|
var hasVoiceChat = false
|
||||||
var canStartVoiceChat = 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)
|
result.append(.mute)
|
||||||
if hasVoiceChat || canStartVoiceChat {
|
if hasVoiceChat || canStartVoiceChat {
|
||||||
result.append(.voiceChat)
|
result.append(.voiceChat)
|
||||||
|
@ -53,7 +53,7 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
|
|||||||
private let action: (PeerInfoHeaderButtonNode, ContextGesture?) -> Void
|
private let action: (PeerInfoHeaderButtonNode, ContextGesture?) -> Void
|
||||||
let referenceNode: ContextReferenceContentNode
|
let referenceNode: ContextReferenceContentNode
|
||||||
let containerNode: ContextControllerSourceNode
|
let containerNode: ContextControllerSourceNode
|
||||||
private let backgroundNode: ASImageNode
|
private let backgroundNode: ASDisplayNode
|
||||||
private let iconNode: ASImageNode
|
private let iconNode: ASImageNode
|
||||||
private let textNode: ImmediateTextNode
|
private let textNode: ImmediateTextNode
|
||||||
private var animationNode: AnimationNode?
|
private var animationNode: AnimationNode?
|
||||||
@ -70,9 +70,8 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
|
|||||||
self.containerNode = ContextControllerSourceNode()
|
self.containerNode = ContextControllerSourceNode()
|
||||||
self.containerNode.animateScale = false
|
self.containerNode.animateScale = false
|
||||||
|
|
||||||
self.backgroundNode = ASImageNode()
|
self.backgroundNode = ASDisplayNode()
|
||||||
self.backgroundNode.displaysAsynchronously = false
|
self.backgroundNode.cornerRadius = 11.0
|
||||||
self.backgroundNode.displayWithoutProcessing = true
|
|
||||||
|
|
||||||
self.iconNode = ASImageNode()
|
self.iconNode = ASImageNode()
|
||||||
self.iconNode.displaysAsynchronously = false
|
self.iconNode.displaysAsynchronously = false
|
||||||
@ -127,6 +126,9 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
|
|||||||
let iconUpdated = self.icon != icon
|
let iconUpdated = self.icon != icon
|
||||||
let isActiveUpdated = self.isActive != isActive
|
let isActiveUpdated = self.isActive != isActive
|
||||||
self.isActive = isActive
|
self.isActive = isActive
|
||||||
|
|
||||||
|
let iconSize = CGSize(width: 40.0, height: 40.0)
|
||||||
|
|
||||||
if self.theme != presentationData.theme || self.icon != icon {
|
if self.theme != presentationData.theme || self.icon != icon {
|
||||||
self.theme = presentationData.theme
|
self.theme = presentationData.theme
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
@ -141,7 +143,7 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
|
|||||||
var colors: [String: UIColor] = [:]
|
var colors: [String: UIColor] = [:]
|
||||||
var playOnce = false
|
var playOnce = false
|
||||||
var seekToEnd = false
|
var seekToEnd = false
|
||||||
let iconColor = presentationData.theme.list.itemCheckColors.foregroundColor
|
let iconColor = presentationData.theme.list.itemAccentColor
|
||||||
switch icon {
|
switch icon {
|
||||||
case .voiceChat:
|
case .voiceChat:
|
||||||
animationName = "anim_profilevc"
|
animationName = "anim_profilevc"
|
||||||
@ -198,7 +200,6 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
|
|||||||
self.referenceNode.addSubnode(animationNode)
|
self.referenceNode.addSubnode(animationNode)
|
||||||
self.animationNode = animationNode
|
self.animationNode = animationNode
|
||||||
}
|
}
|
||||||
animationNode.frame = CGRect(origin: CGPoint(), size: size)
|
|
||||||
} else if let animationNode = self.animationNode {
|
} else if let animationNode = self.animationNode {
|
||||||
self.animationNode = nil
|
self.animationNode = nil
|
||||||
animationNode.removeFromSupernode()
|
animationNode.removeFromSupernode()
|
||||||
@ -210,11 +211,12 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
|
|||||||
self.animationNode?.seekToEnd()
|
self.animationNode?.seekToEnd()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.backgroundNode.image = generateFilledCircleImage(diameter: 40.0, color: presentationData.theme.list.itemAccentColor)
|
self.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
|
||||||
self.iconNode.image = generateImage(CGSize(width: 40.0, height: 40.0), contextGenerator: { size, context in
|
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.clear(CGRect(origin: CGPoint(), size: size))
|
||||||
context.setBlendMode(.normal)
|
context.setBlendMode(.normal)
|
||||||
context.setFillColor(presentationData.theme.list.itemCheckColors.foregroundColor.cgColor)
|
context.setFillColor(iconColor.cgColor)
|
||||||
let imageName: String?
|
let imageName: String?
|
||||||
switch icon {
|
switch icon {
|
||||||
case .message:
|
case .message:
|
||||||
@ -246,24 +248,26 @@ final class PeerInfoHeaderButtonNode: HighlightableButtonNode {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let alpha: CGFloat = isActive ? 1.0 : 0.3
|
if isActiveUpdated {
|
||||||
if isActiveUpdated, !self.containerNode.alpha.isZero {
|
|
||||||
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
let alphaTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
|
||||||
alphaTransition.updateAlpha(node: self.backgroundNode, alpha: isActive ? 1.0 : 0.3)
|
alphaTransition.updateAlpha(node: self.iconNode, alpha: isActive ? 1.0 : 0.3)
|
||||||
if !isExpanded {
|
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)
|
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
|
self.accessibilityLabel = text
|
||||||
let titleSize = self.textNode.updateLayout(CGSize(width: 120.0, height: .greatestFiniteMagnitude))
|
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.containerNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||||
transition.updateFrame(node: self.backgroundNode, 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.updateFrame(node: self.iconNode, 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 + 6.0), size: titleSize))
|
if let animationNode = self.animationNode {
|
||||||
transition.updateAlpha(node: self.textNode, alpha: isExpanded ? 0.0 : alpha)
|
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
|
self.referenceNode.frame = self.containerNode.bounds
|
||||||
}
|
}
|
||||||
@ -1267,9 +1271,9 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
|
|||||||
|
|
||||||
if self.theme !== presentationData.theme {
|
if self.theme !== presentationData.theme {
|
||||||
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.textColor = presentationData.theme.list.itemPrimaryTextColor
|
||||||
self.textNode.textField.keyboardAppearance = presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
self.textNode.textField.keyboardAppearance = presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
||||||
self.textNode.textField.tintColor = presentationData.theme.list.itemAccentColor
|
self.textNode.textField.tintColor = presentationData.theme.list.itemAccentColor
|
||||||
@ -1287,7 +1291,7 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
|
|||||||
self.textNode.textField.text = updateText
|
self.textNode.textField.text = updateText
|
||||||
}
|
}
|
||||||
|
|
||||||
if !hasPrevious && isSettings {
|
if !hasPrevious {
|
||||||
self.topSeparator.isHidden = true
|
self.topSeparator.isHidden = true
|
||||||
}
|
}
|
||||||
self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
||||||
@ -1325,12 +1329,14 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode, ASEditableTextNodeDelegate {
|
final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode, ASEditableTextNodeDelegate {
|
||||||
|
private let backgroundNode: ASDisplayNode
|
||||||
private let textNode: EditableTextNode
|
private let textNode: EditableTextNode
|
||||||
private let textNodeContainer: ASDisplayNode
|
private let textNodeContainer: ASDisplayNode
|
||||||
private let measureTextNode: ImmediateTextNode
|
private let measureTextNode: ImmediateTextNode
|
||||||
private let clearIconNode: ASImageNode
|
private let clearIconNode: ASImageNode
|
||||||
private let clearButtonNode: HighlightableButtonNode
|
private let clearButtonNode: HighlightableButtonNode
|
||||||
private let topSeparator: ASDisplayNode
|
private let topSeparator: ASDisplayNode
|
||||||
|
private let maskNode: ASImageNode
|
||||||
|
|
||||||
private let requestUpdateHeight: () -> Void
|
private let requestUpdateHeight: () -> Void
|
||||||
|
|
||||||
@ -1346,6 +1352,8 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
|
|||||||
init(requestUpdateHeight: @escaping () -> Void) {
|
init(requestUpdateHeight: @escaping () -> Void) {
|
||||||
self.requestUpdateHeight = requestUpdateHeight
|
self.requestUpdateHeight = requestUpdateHeight
|
||||||
|
|
||||||
|
self.backgroundNode = ASDisplayNode()
|
||||||
|
|
||||||
self.textNode = EditableTextNode()
|
self.textNode = EditableTextNode()
|
||||||
self.textNode.clipsToBounds = false
|
self.textNode.clipsToBounds = false
|
||||||
self.textNode.textView.clipsToBounds = false
|
self.textNode.textView.clipsToBounds = false
|
||||||
@ -1365,13 +1373,18 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
|
|||||||
self.clearButtonNode = HighlightableButtonNode()
|
self.clearButtonNode = HighlightableButtonNode()
|
||||||
self.clearButtonNode.isHidden = true
|
self.clearButtonNode.isHidden = true
|
||||||
|
|
||||||
|
self.maskNode = ASImageNode()
|
||||||
|
self.maskNode.isUserInteractionEnabled = false
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
self.addSubnode(self.backgroundNode)
|
||||||
self.textNodeContainer.addSubnode(self.textNode)
|
self.textNodeContainer.addSubnode(self.textNode)
|
||||||
self.addSubnode(self.textNodeContainer)
|
self.addSubnode(self.textNodeContainer)
|
||||||
self.addSubnode(self.clearIconNode)
|
self.addSubnode(self.clearIconNode)
|
||||||
self.addSubnode(self.clearButtonNode)
|
self.addSubnode(self.clearButtonNode)
|
||||||
self.addSubnode(self.topSeparator)
|
self.addSubnode(self.topSeparator)
|
||||||
|
self.addSubnode(self.maskNode)
|
||||||
|
|
||||||
self.clearButtonNode.addTarget(self, action: #selector(self.clearButtonPressed), forControlEvents: .touchUpInside)
|
self.clearButtonNode.addTarget(self, action: #selector(self.clearButtonPressed), forControlEvents: .touchUpInside)
|
||||||
self.clearButtonNode.highligthedChanged = { [weak self] highlighted in
|
self.clearButtonNode.highligthedChanged = { [weak self] highlighted in
|
||||||
@ -1411,8 +1424,10 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
|
|||||||
|
|
||||||
if self.theme !== presentationData.theme {
|
if self.theme !== presentationData.theme {
|
||||||
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.typingAttributes = [NSAttributedString.Key.font.rawValue: titleFont, NSAttributedString.Key.foregroundColor.rawValue: textColor]
|
||||||
self.textNode.keyboardAppearance = presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
self.textNode.keyboardAppearance = presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
||||||
self.textNode.tintColor = presentationData.theme.list.itemAccentColor
|
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.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)
|
let attributedPlaceholderText = NSAttributedString(string: placeholder, font: titleFont, textColor: presentationData.theme.list.itemPlaceholderTextColor)
|
||||||
if self.textNode.attributedPlaceholderText == nil || !self.textNode.attributedPlaceholderText!.isEqual(to: attributedPlaceholderText) {
|
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.textNodeContainer.frame = textNodeFrame
|
||||||
self.textNode.frame = CGRect(origin: CGPoint(), size: textNodeFrame.size)
|
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
|
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 {
|
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
|
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))
|
let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 13.0), size: CGSize(width: avatarSize, height: avatarSize))
|
||||||
if isSettings {
|
|
||||||
avatarFrame = avatarFrame.offsetBy(dx: 0.0, dy: 3.0)
|
|
||||||
}
|
|
||||||
transition.updateFrameAdditiveToCenter(node: self.avatarNode, frame: CGRect(origin: avatarFrame.center, size: CGSize()))
|
transition.updateFrameAdditiveToCenter(node: self.avatarNode, frame: CGRect(origin: avatarFrame.center, size: CGSize()))
|
||||||
|
|
||||||
var contentHeight: CGFloat = statusBarHeight + 10.0 + avatarSize + 20.0
|
var contentHeight: CGFloat = statusBarHeight + 10.0 + avatarSize + 20.0
|
||||||
@ -1691,12 +1714,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
private let videoCallsEnabled: Bool
|
private let videoCallsEnabled: Bool
|
||||||
|
|
||||||
private(set) var isAvatarExpanded: Bool
|
private(set) var isAvatarExpanded: Bool
|
||||||
private(set) var twoLineInfo = false
|
|
||||||
var skipCollapseCompletion = false
|
var skipCollapseCompletion = false
|
||||||
var ignoreCollapse = false
|
var ignoreCollapse = false
|
||||||
|
|
||||||
let avatarListNode: PeerInfoAvatarListNode
|
let avatarListNode: PeerInfoAvatarListNode
|
||||||
|
|
||||||
|
let buttonsContainerNode: SparseNode
|
||||||
let regularContentNode: PeerInfoHeaderRegularContentNode
|
let regularContentNode: PeerInfoHeaderRegularContentNode
|
||||||
let editingContentNode: PeerInfoHeaderEditingContentNode
|
let editingContentNode: PeerInfoHeaderEditingContentNode
|
||||||
let avatarOverlayNode: PeerInfoEditingAvatarOverlayNode
|
let avatarOverlayNode: PeerInfoEditingAvatarOverlayNode
|
||||||
@ -1735,6 +1758,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
var navigationTransition: PeerInfoHeaderNavigationTransition?
|
var navigationTransition: PeerInfoHeaderNavigationTransition?
|
||||||
|
|
||||||
|
var backgroundAlpha: CGFloat = 1.0
|
||||||
var updateHeaderAlpha: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
|
var updateHeaderAlpha: ((CGFloat, ContainedViewLayoutTransition) -> Void)?
|
||||||
|
|
||||||
init(context: AccountContext, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isSettings: Bool) {
|
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 = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
|
||||||
self.usernameNode.displaysAsynchronously = false
|
self.usernameNode.displaysAsynchronously = false
|
||||||
|
|
||||||
|
self.buttonsContainerNode = SparseNode()
|
||||||
|
self.buttonsContainerNode.clipsToBounds = true
|
||||||
|
|
||||||
self.regularContentNode = PeerInfoHeaderRegularContentNode()
|
self.regularContentNode = PeerInfoHeaderRegularContentNode()
|
||||||
var requestUpdateLayoutImpl: (() -> Void)?
|
var requestUpdateLayoutImpl: (() -> Void)?
|
||||||
self.editingContentNode = PeerInfoHeaderEditingContentNode(context: context, requestUpdateLayout: {
|
self.editingContentNode = PeerInfoHeaderEditingContentNode(context: context, requestUpdateLayout: {
|
||||||
@ -1813,28 +1840,22 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
self?.requestUpdateLayout?()
|
self?.requestUpdateLayout?()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.addSubnode(self.buttonsContainerNode)
|
||||||
self.addSubnode(self.backgroundNode)
|
self.addSubnode(self.backgroundNode)
|
||||||
self.addSubnode(self.expandedBackgroundNode)
|
self.addSubnode(self.expandedBackgroundNode)
|
||||||
self.titleNodeContainer.addSubnode(self.titleNode)
|
self.titleNodeContainer.addSubnode(self.titleNode)
|
||||||
self.subtitleNodeContainer.addSubnode(self.subtitleNode)
|
self.subtitleNodeContainer.addSubnode(self.subtitleNode)
|
||||||
self.subtitleNodeContainer.addSubnode(self.panelSubtitleNode)
|
self.subtitleNodeContainer.addSubnode(self.panelSubtitleNode)
|
||||||
self.usernameNodeContainer.addSubnode(self.usernameNode)
|
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)
|
||||||
self.regularContentNode.addSubnode(self.avatarListNode.listContainerNode.controlsClippingOffsetNode)
|
self.regularContentNode.addSubnode(self.avatarListNode.listContainerNode.controlsClippingOffsetNode)
|
||||||
if self.isSettings {
|
|
||||||
self.regularContentNode.addSubnode(self.titleNodeContainer)
|
self.regularContentNode.addSubnode(self.titleNodeContainer)
|
||||||
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
|
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
|
||||||
self.regularContentNode.addSubnode(self.subtitleNodeRawContainer)
|
self.regularContentNode.addSubnode(self.subtitleNodeRawContainer)
|
||||||
self.regularContentNode.addSubnode(self.usernameNodeContainer)
|
self.regularContentNode.addSubnode(self.usernameNodeContainer)
|
||||||
self.regularContentNode.addSubnode(self.usernameNodeRawContainer)
|
self.regularContentNode.addSubnode(self.usernameNodeRawContainer)
|
||||||
}
|
|
||||||
self.addSubnode(self.regularContentNode)
|
self.addSubnode(self.regularContentNode)
|
||||||
self.addSubnode(self.editingContentNode)
|
self.addSubnode(self.editingContentNode)
|
||||||
self.addSubnode(self.avatarOverlayNode)
|
self.addSubnode(self.avatarOverlayNode)
|
||||||
@ -2011,6 +2032,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0
|
self.regularContentNode.alpha = state.isEditing ? 0.0 : 1.0
|
||||||
|
self.buttonsContainerNode.alpha = self.regularContentNode.alpha
|
||||||
self.editingContentNode.alpha = state.isEditing ? 1.0 : 0.0
|
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)
|
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)
|
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 {
|
if let navigationTransition = self.navigationTransition, let sourceAvatarNode = (navigationTransition.sourceNavigationBar.rightButtonNode.singleCustomNode as? ChatAvatarNavigationNode)?.avatarNode {
|
||||||
transitionSourceHeight = navigationTransition.sourceNavigationBar.backgroundNode.bounds.height
|
transitionSourceHeight = navigationTransition.sourceNavigationBar.backgroundNode.bounds.height
|
||||||
transitionFraction = navigationTransition.fraction
|
transitionFraction = navigationTransition.fraction
|
||||||
@ -2034,15 +2058,18 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
transitionSourceTitleFrame = navigationTransition.sourceTitleFrame
|
transitionSourceTitleFrame = navigationTransition.sourceTitleFrame
|
||||||
transitionSourceSubtitleFrame = navigationTransition.sourceSubtitleFrame
|
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 {
|
if self.isAvatarExpanded, case .animated = transition, transitionFraction == 1.0 {
|
||||||
self.avatarListNode.animateAvatarCollapse(transition: transition)
|
self.avatarListNode.animateAvatarCollapse(transition: transition)
|
||||||
}
|
}
|
||||||
} else {
|
} 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)
|
self.avatarListNode.avatarContainerNode.updateTransitionFraction(transitionFraction, transition: transition)
|
||||||
@ -2062,13 +2089,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
self.navigationBackgroundBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.opaqueBackgroundColor
|
self.navigationBackgroundBackgroundNode.backgroundColor = presentationData.theme.rootController.navigationBar.opaqueBackgroundColor
|
||||||
self.navigationSeparatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor
|
self.navigationSeparatorNode.backgroundColor = presentationData.theme.rootController.navigationBar.separatorColor
|
||||||
|
|
||||||
let separatorAlpha: CGFloat = state.isEditing && self.isSettings ? min(1.0, contentOffset / (navigationHeight * 0.5)) : 0.0
|
let navigationSeparatorAlpha: 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.navigationBackgroundBackgroundNode, alpha: 1.0 - navigationSeparatorAlpha)
|
||||||
transition.updateAlpha(node: self.navigationSeparatorNode, alpha: separatorAlpha)
|
transition.updateAlpha(node: self.navigationSeparatorNode, alpha: navigationSeparatorAlpha)
|
||||||
|
|
||||||
self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
self.separatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
||||||
|
|
||||||
let defaultButtonSize: CGFloat = 40.0
|
|
||||||
let expandedAvatarControlsHeight: CGFloat = 61.0
|
let expandedAvatarControlsHeight: CGFloat = 61.0
|
||||||
let expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight)
|
let expandedAvatarListHeight = min(width, containerHeight - expandedAvatarControlsHeight)
|
||||||
let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight)
|
let expandedAvatarListSize = CGSize(width: width, height: expandedAvatarListHeight)
|
||||||
@ -2105,13 +2131,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
title = " "
|
title = " "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.isSettings {
|
// if self.isSettings {
|
||||||
titleString = NSAttributedString(string: title, font: Font.medium(29.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
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)
|
smallTitleString = NSAttributedString(string: title, font: Font.semibold(28.0), textColor: .white)
|
||||||
} else {
|
// } else {
|
||||||
titleString = NSAttributedString(string: title, font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
// titleString = NSAttributedString(string: title, font: Font.semibold(24.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||||
smallTitleString = titleString
|
// smallTitleString = titleString
|
||||||
}
|
// }
|
||||||
if self.isSettings, let user = peer as? TelegramUser {
|
if self.isSettings, let user = peer as? TelegramUser {
|
||||||
var subtitle = formatPhoneNumber(user.phone ?? "")
|
var subtitle = formatPhoneNumber(user.phone ?? "")
|
||||||
|
|
||||||
@ -2128,8 +2154,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
||||||
}
|
}
|
||||||
subtitleString = NSAttributedString(string: statusData.text, font: Font.regular(15.0), textColor: subtitleColor)
|
smallSubtitleString = NSAttributedString(string: statusData.text, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.7))
|
||||||
smallSubtitleString = subtitleString
|
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)
|
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
|
|
||||||
if let panelStatusData = panelStatusData {
|
if let panelStatusData = panelStatusData {
|
||||||
@ -2139,7 +2165,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
subtitleColor = presentationData.theme.list.itemSecondaryTextColor
|
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 {
|
} else {
|
||||||
subtitleString = NSAttributedString(string: " ", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
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)
|
usernameString = NSAttributedString(string: "", font: Font.regular(15.0), textColor: presentationData.theme.list.itemSecondaryTextColor)
|
||||||
}
|
}
|
||||||
|
|
||||||
let textSideInset: CGFloat = 44.0
|
let textSideInset: CGFloat = 36.0
|
||||||
var expandedAvatarHeight: CGFloat = expandedAvatarListSize.height
|
let expandedAvatarHeight: CGFloat = expandedAvatarListSize.height
|
||||||
if !self.isSettings {
|
|
||||||
expandedAvatarHeight += expandedAvatarControlsHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
let titleConstrainedSize = CGSize(width: width - textSideInset * 2.0 - (isVerified ? 16.0 : 0.0), height: .greatestFiniteMagnitude)
|
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: [
|
let subtitleNodeLayout = self.subtitleNode.updateLayout(states: [
|
||||||
TitleNodeStateRegular: MultiScaleTextState(attributedText: subtitleString, constrainedSize: titleConstrainedSize),
|
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)
|
], mainState: TitleNodeStateRegular)
|
||||||
self.subtitleNode.accessibilityLabel = subtitleString.string
|
self.subtitleNode.accessibilityLabel = subtitleString.string
|
||||||
|
|
||||||
let panelSubtitleNodeLayout = self.panelSubtitleNode.updateLayout(states: [
|
let panelSubtitleNodeLayout = self.panelSubtitleNode.updateLayout(states: [
|
||||||
TitleNodeStateRegular: MultiScaleTextState(attributedText: panelSubtitleString ?? subtitleString, constrainedSize: titleConstrainedSize),
|
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)
|
], mainState: TitleNodeStateRegular)
|
||||||
self.panelSubtitleNode.accessibilityLabel = (panelSubtitleString ?? subtitleString).string
|
self.panelSubtitleNode.accessibilityLabel = (panelSubtitleString ?? subtitleString).string
|
||||||
|
|
||||||
@ -2186,10 +2209,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
], mainState: TitleNodeStateRegular)
|
], mainState: TitleNodeStateRegular)
|
||||||
self.usernameNode.accessibilityLabel = usernameString.string
|
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))
|
let avatarFrame = CGRect(origin: CGPoint(x: floor((width - avatarSize) / 2.0), y: statusBarHeight + 13.0), size: CGSize(width: avatarSize, height: avatarSize))
|
||||||
if isSettings {
|
|
||||||
avatarFrame = avatarFrame.offsetBy(dx: 0.0, dy: 3.0)
|
|
||||||
}
|
|
||||||
let avatarCenter = CGPoint(x: (1.0 - transitionFraction) * avatarFrame.midX + transitionFraction * transitionSourceAvatarFrame.midX, y: (1.0 - transitionFraction) * avatarFrame.midY + transitionFraction * transitionSourceAvatarFrame.midY)
|
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
|
let titleSize = titleNodeLayout[TitleNodeStateRegular]!.size
|
||||||
@ -2208,34 +2228,25 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
let subtitleFrame: CGRect
|
let subtitleFrame: CGRect
|
||||||
let usernameFrame: CGRect
|
let usernameFrame: CGRect
|
||||||
let usernameSpacing: CGFloat = 4.0
|
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 {
|
if self.isAvatarExpanded {
|
||||||
let minTitleSize = CGSize(width: titleSize.width * 0.7, height: titleSize.height * 0.7)
|
let minTitleSize = CGSize(width: titleSize.width * 0.7, height: titleSize.height * 0.7)
|
||||||
let minTitleFrame: CGRect
|
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)
|
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)
|
|
||||||
}
|
|
||||||
titleFrame = CGRect(origin: CGPoint(x: minTitleFrame.midX - titleSize.width / 2.0, y: minTitleFrame.midY - titleSize.height / 2.0), size: titleSize)
|
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)
|
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)
|
|
||||||
}
|
|
||||||
usernameFrame = CGRect(origin: CGPoint(x: width - usernameSize.width - 16.0, y: minTitleFrame.midY - usernameSize.height / 2.0), size: usernameSize)
|
usernameFrame = CGRect(origin: CGPoint(x: width - usernameSize.width - 16.0, y: minTitleFrame.midY - usernameSize.height / 2.0), size: usernameSize)
|
||||||
} else {
|
} 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)
|
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
|
let totalSubtitleWidth = subtitleSize.width + usernameSpacing + usernameSize.width
|
||||||
twoLineInfo = false
|
if usernameSize.width == 0.0 {
|
||||||
if usernameSize.width == 0.0 || twoLineInfo {
|
|
||||||
subtitleFrame = CGRect(origin: CGPoint(x: floor((width - subtitleSize.width) / 2.0), y: titleFrame.maxY + 1.0), size: subtitleSize)
|
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)
|
usernameFrame = CGRect(origin: CGPoint(x: floor((width - usernameSize.width) / 2.0), y: subtitleFrame.maxY + 1.0), size: usernameSize)
|
||||||
} else {
|
} else {
|
||||||
@ -2243,7 +2254,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
usernameFrame = CGRect(origin: CGPoint(x: subtitleFrame.maxX + usernameSpacing, y: titleFrame.maxY + 1.0), size: usernameSize)
|
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
|
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 titleOffset = -min(titleCollapseOffset, contentOffset)
|
||||||
let titleCollapseFraction = max(0.0, min(1.0, contentOffset / titleCollapseOffset))
|
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 subtitleMinScale: CGFloat = 0.8
|
||||||
let avatarMinScale: CGFloat = 0.7
|
let avatarMinScale: CGFloat = 0.7
|
||||||
|
|
||||||
@ -2273,6 +2283,12 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
effectiveAreaExpansionFraction = 1.0 - paneAreaExpansionDelta / paneAreaExpansionDistance
|
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: [
|
self.titleNode.update(stateFractions: [
|
||||||
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
|
TitleNodeStateRegular: self.isAvatarExpanded ? 0.0 : 1.0,
|
||||||
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
|
TitleNodeStateExpanded: self.isAvatarExpanded ? 1.0 : 0.0
|
||||||
@ -2285,12 +2301,6 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
if self.isSettings {
|
if self.isSettings {
|
||||||
subtitleAlpha = 1.0 - titleCollapseFraction
|
subtitleAlpha = 1.0 - titleCollapseFraction
|
||||||
panelSubtitleAlpha = 0.0
|
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 {
|
} else {
|
||||||
if (panelSubtitleString ?? subtitleString).string != subtitleString.string {
|
if (panelSubtitleString ?? subtitleString).string != subtitleString.string {
|
||||||
subtitleAlpha = 1.0 - effectiveAreaExpansionFraction
|
subtitleAlpha = 1.0 - effectiveAreaExpansionFraction
|
||||||
@ -2422,23 +2432,19 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
self.avatarListNode.avatarContainerNode.canAttachVideo = false
|
self.avatarListNode.avatarContainerNode.canAttachVideo = false
|
||||||
}
|
}
|
||||||
|
|
||||||
var panelWithAvatarHeight: CGFloat = (self.isSettings ? 40.0 : 112.0) + avatarSize
|
let panelWithAvatarHeight: CGFloat = 40.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 rawHeight: CGFloat
|
let rawHeight: CGFloat
|
||||||
let height: CGFloat
|
let height: CGFloat
|
||||||
|
let maxY: CGFloat
|
||||||
if self.isAvatarExpanded {
|
if self.isAvatarExpanded {
|
||||||
rawHeight = expandedAvatarHeight
|
rawHeight = expandedAvatarHeight
|
||||||
height = max(navigationHeight, rawHeight - contentOffset)
|
height = max(navigationHeight, rawHeight - contentOffset)
|
||||||
|
maxY = height
|
||||||
} else {
|
} else {
|
||||||
rawHeight = navigationHeight + panelWithAvatarHeight
|
rawHeight = navigationHeight + panelWithAvatarHeight
|
||||||
height = navigationHeight + max(0.0, panelWithAvatarHeight - contentOffset)
|
height = navigationHeight + max(0.0, panelWithAvatarHeight - contentOffset)
|
||||||
|
maxY = navigationHeight + panelWithAvatarHeight - contentOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
let apparentHeight = (1.0 - transitionFraction) * height + transitionFraction * transitionSourceHeight
|
let apparentHeight = (1.0 - transitionFraction) * height + transitionFraction * transitionSourceHeight
|
||||||
@ -2474,12 +2480,14 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
let titleScale: CGFloat
|
let titleScale: CGFloat
|
||||||
let subtitleScale: CGFloat
|
let subtitleScale: CGFloat
|
||||||
|
var subtitleOffset: CGFloat = 0.0
|
||||||
if self.isAvatarExpanded {
|
if self.isAvatarExpanded {
|
||||||
titleScale = 0.7
|
titleScale = 0.7
|
||||||
subtitleScale = 1.0
|
subtitleScale = 1.0
|
||||||
} else {
|
} else {
|
||||||
titleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * titleMinScale
|
titleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * titleMinScale
|
||||||
subtitleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * subtitleMinScale
|
subtitleScale = (1.0 - titleCollapseFraction) * 1.0 + titleCollapseFraction * subtitleMinScale
|
||||||
|
subtitleOffset = titleCollapseFraction * -2.0
|
||||||
}
|
}
|
||||||
|
|
||||||
let rawTitleFrame = titleFrame
|
let rawTitleFrame = titleFrame
|
||||||
@ -2498,6 +2506,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
var subtitleCenter = rawSubtitleFrame.center
|
var subtitleCenter = rawSubtitleFrame.center
|
||||||
subtitleCenter.x = rawTitleFrame.center.x + (subtitleCenter.x - rawTitleFrame.center.x) * subtitleScale
|
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))
|
transition.updateFrameAdditiveToCenter(node: self.subtitleNodeContainer, frame: CGRect(origin: subtitleCenter, size: CGSize()).offsetBy(dx: 0.0, dy: titleOffset))
|
||||||
|
|
||||||
var usernameCenter = rawUsernameFrame.center
|
var usernameCenter = rawUsernameFrame.center
|
||||||
@ -2513,63 +2522,16 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let buttonSpacing: CGFloat
|
let buttonSpacing: CGFloat = 12.0
|
||||||
if self.isAvatarExpanded {
|
var buttonRightOrigin = CGPoint(x: width - containerInset, y: maxY + 25.0 - navigationHeight - UIScreenPixel)
|
||||||
buttonSpacing = 16.0
|
let buttonWidth = (width - containerInset * 2.0 + buttonSpacing) / CGFloat(buttonKeys.count) - buttonSpacing
|
||||||
} 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 expandedButtonSize: CGFloat = 32.0
|
let apparentButtonSize = CGSize(width: buttonWidth, height: 58.0)
|
||||||
let buttonsWidth = buttonSpacing * CGFloat(buttonKeys.count - 1) + CGFloat(buttonKeys.count) * defaultButtonSize
|
let buttonsAlpha: CGFloat = 1.0
|
||||||
var buttonRightOrigin: CGPoint
|
let buttonsVerticalOffset: CGFloat = 0.0
|
||||||
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
|
|
||||||
|
|
||||||
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() {
|
for buttonKey in buttonKeys.reversed() {
|
||||||
let buttonNode: PeerInfoHeaderButtonNode
|
let buttonNode: PeerInfoHeaderButtonNode
|
||||||
var wasAdded = false
|
var wasAdded = false
|
||||||
@ -2581,10 +2543,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
self?.buttonPressed(buttonNode, gesture: gesture)
|
self?.buttonPressed(buttonNode, gesture: gesture)
|
||||||
})
|
})
|
||||||
self.buttonNodes[buttonKey] = buttonNode
|
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 buttonTransition: ContainedViewLayoutTransition = wasAdded ? .immediate : transition
|
||||||
|
|
||||||
let apparentButtonFrame = buttonFrame.offsetBy(dx: 0.0, dy: buttonsVerticalOffset)
|
let apparentButtonFrame = buttonFrame.offsetBy(dx: 0.0, dy: buttonsVerticalOffset)
|
||||||
@ -2642,28 +2604,13 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
isActive = buttonKey == highlightedButton
|
isActive = buttonKey == highlightedButton
|
||||||
}
|
}
|
||||||
|
|
||||||
buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isActive: isActive, isExpanded: self.isAvatarExpanded, presentationData: presentationData, transition: buttonTransition)
|
buttonNode.update(size: buttonFrame.size, text: buttonText, icon: buttonIcon, isActive: isActive, isExpanded: false, presentationData: presentationData, transition: buttonTransition)
|
||||||
transition.updateSublayerTransformScaleAdditive(node: buttonNode, scale: buttonsScale)
|
|
||||||
|
|
||||||
if wasAdded {
|
if wasAdded {
|
||||||
buttonNode.alpha = 0.0
|
buttonNode.alpha = 0.0
|
||||||
}
|
}
|
||||||
buttonsAlphaTransition.updateAlpha(node: buttonNode, alpha: buttonsAlpha)
|
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 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 .mute = buttonKey, buttonNode.containerNode.alpha.isZero, additive {
|
||||||
if case let .animated(duration, curve) = transition {
|
if case let .animated(duration, curve) = transition {
|
||||||
ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
|
ContainedViewLayoutTransition.animated(duration: duration * 0.3, curve: curve).updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
|
||||||
@ -2673,8 +2620,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
} else {
|
} else {
|
||||||
transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
|
transition.updateAlpha(node: buttonNode.containerNode, alpha: 1.0)
|
||||||
}
|
}
|
||||||
buttonRightOrigin.x -= apparentButtonSize + buttonSpacing
|
buttonRightOrigin.x -= apparentButtonSize.width + buttonSpacing
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for key in self.buttonNodes.keys {
|
for key in self.buttonNodes.keys {
|
||||||
@ -2690,11 +2636,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
|
|
||||||
let resolvedRegularHeight: CGFloat
|
let resolvedRegularHeight: CGFloat
|
||||||
if self.isAvatarExpanded {
|
if self.isAvatarExpanded {
|
||||||
if self.isSettings {
|
|
||||||
resolvedRegularHeight = expandedAvatarListSize.height
|
resolvedRegularHeight = expandedAvatarListSize.height
|
||||||
} else {
|
|
||||||
resolvedRegularHeight = expandedAvatarListSize.height + expandedAvatarControlsHeight
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
resolvedRegularHeight = panelWithAvatarHeight + navigationHeight
|
resolvedRegularHeight = panelWithAvatarHeight + navigationHeight
|
||||||
}
|
}
|
||||||
@ -2703,6 +2645,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||||||
let separatorFrame: CGRect
|
let separatorFrame: CGRect
|
||||||
|
|
||||||
let resolvedHeight: CGFloat
|
let resolvedHeight: CGFloat
|
||||||
|
|
||||||
if state.isEditing {
|
if state.isEditing {
|
||||||
resolvedHeight = editingContentHeight
|
resolvedHeight = editingContentHeight
|
||||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: -2000.0 + max(navigationHeight, resolvedHeight - contentOffset)), size: CGSize(width: width, height: 2000.0))
|
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.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 {
|
if additive {
|
||||||
transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame)
|
transition.updateFrameAdditive(node: self.backgroundNode, frame: backgroundFrame)
|
||||||
|
@ -92,6 +92,7 @@ enum PeerInfoMembersDataState: Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct PeerInfoMembersState: Equatable {
|
struct PeerInfoMembersState: Equatable {
|
||||||
|
var canAddMembers: Bool
|
||||||
var members: [PeerInfoMember]
|
var members: [PeerInfoMember]
|
||||||
var dataState: PeerInfoMembersDataState
|
var dataState: PeerInfoMembersDataState
|
||||||
}
|
}
|
||||||
@ -126,6 +127,7 @@ private final class PeerInfoMembersContextImpl {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
|
|
||||||
|
private var canAddMembers = false
|
||||||
private var members: [PeerInfoMember] = []
|
private var members: [PeerInfoMember] = []
|
||||||
private var dataState: PeerInfoMembersDataState = .loading(isInitial: true)
|
private var dataState: PeerInfoMembersDataState = .loading(isInitial: true)
|
||||||
private var removingMemberIds: [PeerId: Disposable] = [:]
|
private var removingMemberIds: [PeerId: Disposable] = [:]
|
||||||
@ -135,7 +137,7 @@ private final class PeerInfoMembersContextImpl {
|
|||||||
return self.stateValue.get()
|
return self.stateValue.get()
|
||||||
}
|
}
|
||||||
private let disposable = MetaDisposable()
|
private let disposable = MetaDisposable()
|
||||||
|
private let peerDisposable = MetaDisposable()
|
||||||
private var channelMembersControl: PeerChannelMemberCategoryControl?
|
private var channelMembersControl: PeerChannelMemberCategoryControl?
|
||||||
|
|
||||||
init(queue: Queue, context: AccountContext, peerId: PeerId) {
|
init(queue: Queue, context: AccountContext, peerId: PeerId) {
|
||||||
@ -170,8 +172,28 @@ private final class PeerInfoMembersContextImpl {
|
|||||||
})
|
})
|
||||||
self.disposable.set(disposable)
|
self.disposable.set(disposable)
|
||||||
self.channelMembersControl = control
|
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 {
|
} 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
|
|> deliverOn(self.queue)).start(next: { [weak self] view in
|
||||||
guard let strongSelf = self, let cachedData = view.cachedData as? CachedGroupData, let participantsData = cachedData.participants else {
|
guard let strongSelf = self, let cachedData = view.cachedData as? CachedGroupData, let participantsData = cachedData.participants else {
|
||||||
return
|
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))
|
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.members = membersSortedByPresence(unsortedMembers, accountPeerId: strongSelf.context.account.peerId)
|
||||||
strongSelf.dataState = .ready(canLoadMore: false)
|
strongSelf.dataState = .ready(canLoadMore: false)
|
||||||
strongSelf.pushState()
|
strongSelf.pushState()
|
||||||
@ -207,13 +244,14 @@ private final class PeerInfoMembersContextImpl {
|
|||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.disposable.dispose()
|
self.disposable.dispose()
|
||||||
|
self.peerDisposable.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func pushState() {
|
private func pushState() {
|
||||||
if self.removingMemberIds.isEmpty {
|
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 {
|
} 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
|
return self.removingMemberIds[member.id] == nil
|
||||||
}, dataState: self.dataState)))
|
}, dataState: self.dataState)))
|
||||||
}
|
}
|
||||||
|
@ -383,6 +383,7 @@ private final class PeerInfoPendingPane {
|
|||||||
chatControllerInteraction: ChatControllerInteraction,
|
chatControllerInteraction: ChatControllerInteraction,
|
||||||
data: PeerInfoScreenData,
|
data: PeerInfoScreenData,
|
||||||
openPeerContextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void,
|
openPeerContextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void,
|
||||||
|
openAddMemberAction: @escaping () -> Void,
|
||||||
requestPerformPeerMemberAction: @escaping (PeerInfoMember, PeerMembersListAction) -> Void,
|
requestPerformPeerMemberAction: @escaping (PeerInfoMember, PeerMembersListAction) -> Void,
|
||||||
peerId: PeerId,
|
peerId: PeerId,
|
||||||
key: PeerInfoPaneKey,
|
key: PeerInfoPaneKey,
|
||||||
@ -423,7 +424,9 @@ private final class PeerInfoPendingPane {
|
|||||||
paneNode = PeerInfoGroupsInCommonPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, openPeerContextAction: openPeerContextAction, groupsInCommonContext: data.groupsInCommon!)
|
paneNode = PeerInfoGroupsInCommonPaneNode(context: context, peerId: peerId, chatControllerInteraction: chatControllerInteraction, openPeerContextAction: openPeerContextAction, groupsInCommonContext: data.groupsInCommon!)
|
||||||
case .members:
|
case .members:
|
||||||
if case let .longList(membersContext) = data.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)
|
requestPerformPeerMemberAction(member, action)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -487,6 +490,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
|||||||
|
|
||||||
var chatControllerInteraction: ChatControllerInteraction?
|
var chatControllerInteraction: ChatControllerInteraction?
|
||||||
var openPeerContextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)?
|
var openPeerContextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)?
|
||||||
|
var openAddMemberAction: (() -> Void)?
|
||||||
var requestPerformPeerMemberAction: ((PeerInfoMember, PeerMembersListAction) -> Void)?
|
var requestPerformPeerMemberAction: ((PeerInfoMember, PeerMembersListAction) -> Void)?
|
||||||
|
|
||||||
var currentPaneUpdated: ((Bool) -> Void)?
|
var currentPaneUpdated: ((Bool) -> Void)?
|
||||||
@ -517,7 +521,7 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
self.addSubnode(self.separatorNode)
|
// self.addSubnode(self.separatorNode)
|
||||||
self.addSubnode(self.coveringBackgroundNode)
|
self.addSubnode(self.coveringBackgroundNode)
|
||||||
self.addSubnode(self.tabsContainerNode)
|
self.addSubnode(self.tabsContainerNode)
|
||||||
self.addSubnode(self.tabsSeparatorNode)
|
self.addSubnode(self.tabsSeparatorNode)
|
||||||
@ -772,6 +776,9 @@ final class PeerInfoPaneContainerNode: ASDisplayNode, UIGestureRecognizerDelegat
|
|||||||
openPeerContextAction: { [weak self] peer, node, gesture in
|
openPeerContextAction: { [weak self] peer, node, gesture in
|
||||||
self?.openPeerContextAction?(peer, node, gesture)
|
self?.openPeerContextAction?(peer, node, gesture)
|
||||||
},
|
},
|
||||||
|
openAddMemberAction: { [weak self] in
|
||||||
|
self?.openAddMemberAction?()
|
||||||
|
},
|
||||||
requestPerformPeerMemberAction: { [weak self] member, action in
|
requestPerformPeerMemberAction: { [weak self] member, action in
|
||||||
self?.requestPerformPeerMemberAction?(member, action)
|
self?.requestPerformPeerMemberAction?(member, action)
|
||||||
},
|
},
|
||||||
|
@ -71,7 +71,7 @@ protocol PeerInfoScreenItem: AnyObject {
|
|||||||
class PeerInfoScreenItemNode: ASDisplayNode, AccessibilityFocusableNode {
|
class PeerInfoScreenItemNode: ASDisplayNode, AccessibilityFocusableNode {
|
||||||
var bringToFrontForHighlight: (() -> Void)?
|
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()
|
preconditionFailure()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,18 +110,13 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode {
|
|||||||
self.addSubnode(self.bottomSeparatorNode)
|
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.backgroundNode.backgroundColor = presentationData.theme.list.itemBlocksBackgroundColor
|
||||||
self.topSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
self.topSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
||||||
self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
self.bottomSeparatorNode.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
||||||
|
|
||||||
if safeInsets.left > 0.0 {
|
self.topSeparatorNode.isHidden = hasCorners
|
||||||
self.topSeparatorNode.isHidden = true
|
self.bottomSeparatorNode.isHidden = hasCorners
|
||||||
self.bottomSeparatorNode.isHidden = true
|
|
||||||
} else {
|
|
||||||
self.topSeparatorNode.isHidden = false
|
|
||||||
self.bottomSeparatorNode.isHidden = false
|
|
||||||
}
|
|
||||||
|
|
||||||
var contentHeight: CGFloat = 0.0
|
var contentHeight: CGFloat = 0.0
|
||||||
var contentWithBackgroundHeight: CGFloat = 0.0
|
var contentWithBackgroundHeight: CGFloat = 0.0
|
||||||
@ -167,7 +162,7 @@ private final class PeerInfoScreenItemSectionContainerNode: ASDisplayNode {
|
|||||||
bottomItem = items[i + 1]
|
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))
|
let itemFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: width, height: itemHeight))
|
||||||
itemTransition.updateFrame(node: itemNode, frame: itemFrame)
|
itemTransition.updateFrame(node: itemNode, frame: itemFrame)
|
||||||
if wasAdded {
|
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 {
|
final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
@ -589,6 +457,7 @@ private final class PeerInfoInteraction {
|
|||||||
let updateBio: (String) -> Void
|
let updateBio: (String) -> Void
|
||||||
let openDeletePeer: () -> Void
|
let openDeletePeer: () -> Void
|
||||||
let openFaq: (String?) -> Void
|
let openFaq: (String?) -> Void
|
||||||
|
let openAddMember: () -> Void
|
||||||
|
|
||||||
init(
|
init(
|
||||||
openUsername: @escaping (String) -> Void,
|
openUsername: @escaping (String) -> Void,
|
||||||
@ -628,7 +497,8 @@ private final class PeerInfoInteraction {
|
|||||||
accountContextMenu: @escaping (AccountRecordId, ASDisplayNode, ContextGesture?) -> Void,
|
accountContextMenu: @escaping (AccountRecordId, ASDisplayNode, ContextGesture?) -> Void,
|
||||||
updateBio: @escaping (String) -> Void,
|
updateBio: @escaping (String) -> Void,
|
||||||
openDeletePeer: @escaping () -> Void,
|
openDeletePeer: @escaping () -> Void,
|
||||||
openFaq: @escaping (String?) -> Void
|
openFaq: @escaping (String?) -> Void,
|
||||||
|
openAddMember: @escaping () -> Void
|
||||||
) {
|
) {
|
||||||
self.openUsername = openUsername
|
self.openUsername = openUsername
|
||||||
self.openPhone = openPhone
|
self.openPhone = openPhone
|
||||||
@ -668,6 +538,7 @@ private final class PeerInfoInteraction {
|
|||||||
self.updateBio = updateBio
|
self.updateBio = updateBio
|
||||||
self.openDeletePeer = openDeletePeer
|
self.openDeletePeer = openDeletePeer
|
||||||
self.openFaq = openFaq
|
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 {
|
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 {
|
for member in memberList {
|
||||||
let isAccountPeer = member.id == context.account.peerId
|
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
|
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?>()
|
fileprivate let cachedDataPromise = Promise<CachedPeerData?>()
|
||||||
|
|
||||||
let scrollNode: ASScrollNode
|
let scrollNode: ASScrollNode
|
||||||
private let leftOverlayNode: ASDisplayNode
|
|
||||||
private let rightOverlayNode: ASDisplayNode
|
|
||||||
|
|
||||||
let headerNode: PeerInfoHeaderNode
|
let headerNode: PeerInfoHeaderNode
|
||||||
private var regularSections: [AnyHashable: PeerInfoScreenItemSectionContainerNode] = [:]
|
private var regularSections: [AnyHashable: PeerInfoScreenItemSectionContainerNode] = [:]
|
||||||
@ -1641,11 +1538,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
self.scrollNode.view.delaysContentTouches = false
|
self.scrollNode.view.delaysContentTouches = false
|
||||||
self.scrollNode.canCancelAllTouchesInViews = true
|
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.headerNode = PeerInfoHeaderNode(context: context, avatarInitiallyExpanded: avatarInitiallyExpanded, isOpenedFromChat: isOpenedFromChat, isSettings: isSettings)
|
||||||
self.paneContainerNode = PeerInfoPaneContainerNode(context: context, updatedPresentationData: controller.updatedPresentationData, peerId: peerId, isMediaOnly: self.isMediaOnly)
|
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.paneContainerNode.parentController = controller
|
||||||
|
|
||||||
self.headerNode.updateHeaderAlpha = { [weak self] alpha, transition in
|
|
||||||
self?.updateHeaderBackgroundAlpha(alpha, transition: transition)
|
|
||||||
}
|
|
||||||
|
|
||||||
self._interaction = PeerInfoInteraction(
|
self._interaction = PeerInfoInteraction(
|
||||||
openUsername: { [weak self] value in
|
openUsername: { [weak self] value in
|
||||||
self?.openUsername(value: value)
|
self?.openUsername(value: value)
|
||||||
@ -1771,6 +1659,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
},
|
},
|
||||||
openFaq: { [weak self] anchor in
|
openFaq: { [weak self] anchor in
|
||||||
self?.openFaq(anchor: anchor)
|
self?.openFaq(anchor: anchor)
|
||||||
|
},
|
||||||
|
openAddMember: { [weak self] in
|
||||||
|
self?.openAddMember()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -2283,13 +2174,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
self.addSubnode(self.scrollNode)
|
self.addSubnode(self.scrollNode)
|
||||||
self.scrollNode.addSubnode(self.paneContainerNode)
|
self.scrollNode.addSubnode(self.paneContainerNode)
|
||||||
|
|
||||||
|
self.addSubnode(self.headerNode.buttonsContainerNode)
|
||||||
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)
|
self.addSubnode(self.headerNode)
|
||||||
self.scrollNode.view.isScrollEnabled = !self.isMediaOnly
|
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
|
self.paneContainerNode.requestPerformPeerMemberAction = { [weak self] member, action in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -2997,10 +2889,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
override func didLoad() {
|
override func didLoad() {
|
||||||
super.didLoad()
|
super.didLoad()
|
||||||
|
|
||||||
if self.isSettings {
|
|
||||||
self.updateHeaderBackgroundAlpha(0.0, transition: .immediate)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.view.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in
|
self.view.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
return strongSelf.state.isEditing
|
return strongSelf.state.isEditing
|
||||||
@ -3010,14 +2898,6 @@ 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?
|
var canAttachVideo: Bool?
|
||||||
|
|
||||||
private func updateData(_ data: PeerInfoScreenData) {
|
private func updateData(_ data: PeerInfoScreenData) {
|
||||||
@ -3613,7 +3493,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
return .single(items)
|
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 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)
|
let filteredButtons = allHeaderButtons.subtracting(headerButtons)
|
||||||
@ -6356,8 +6236,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
|
|
||||||
self.backgroundColor = self.presentationData.theme.list.blocksBackgroundColor
|
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)
|
self.updateNavigationExpansionPresentation(isExpanded: self.headerNode.isAvatarExpanded, animated: false)
|
||||||
|
|
||||||
@ -6395,14 +6273,12 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
} else {
|
} else {
|
||||||
sectionInset = 0.0
|
sectionInset = 0.0
|
||||||
}
|
}
|
||||||
let headerInset: CGFloat
|
let headerInset = sectionInset
|
||||||
if self.isSettings {
|
|
||||||
headerInset = sectionInset
|
|
||||||
} else {
|
|
||||||
headerInset = layout.safeInsets.left
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: headerHeight))
|
||||||
if additive {
|
if additive {
|
||||||
transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame)
|
transition.updateFrameAdditive(node: self.headerNode, frame: headerFrame)
|
||||||
@ -6413,20 +6289,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
contentHeight += navigationHeight
|
contentHeight += navigationHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
var currentInsets = UIEdgeInsets()
|
|
||||||
var validRegularSections: [AnyHashable] = []
|
var validRegularSections: [AnyHashable] = []
|
||||||
if !self.isMediaOnly {
|
if !self.isMediaOnly {
|
||||||
var insets = UIEdgeInsets()
|
var insets = UIEdgeInsets()
|
||||||
if self.isSettings {
|
|
||||||
insets.left += sectionInset
|
insets.left += sectionInset
|
||||||
insets.right += sectionInset
|
insets.right += sectionInset
|
||||||
} else {
|
|
||||||
insets = layout.safeInsets
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.state.isEditing {
|
|
||||||
currentInsets = insets
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
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)
|
||||||
|
|
||||||
@ -6454,8 +6321,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
transition.updateAlpha(node: sectionNode, alpha: 1.0, delay: 0.1)
|
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 sectionWidth = layout.size.width - insets.left - insets.right
|
||||||
let sectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: sectionHeight))
|
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 {
|
if additive {
|
||||||
transition.updateFrameAdditive(node: sectionNode, frame: sectionFrame)
|
transition.updateFrameAdditive(node: sectionNode, frame: sectionFrame)
|
||||||
} else {
|
} else {
|
||||||
@ -6501,10 +6369,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
insets.left += sectionInset
|
insets.left += sectionInset
|
||||||
insets.right += sectionInset
|
insets.right += sectionInset
|
||||||
|
|
||||||
if self.state.isEditing {
|
|
||||||
currentInsets = insets
|
|
||||||
}
|
|
||||||
|
|
||||||
validEditingSections.append(sectionId)
|
validEditingSections.append(sectionId)
|
||||||
|
|
||||||
var wasAdded = false
|
var wasAdded = false
|
||||||
@ -6518,8 +6382,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
self.scrollNode.addSubnode(sectionNode)
|
self.scrollNode.addSubnode(sectionNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
let sectionHeight = sectionNode.update(width: layout.size.width, safeInsets: insets, presentationData: self.presentationData, items: sectionItems, transition: transition)
|
let sectionWidth = layout.size.width - insets.left - insets.right
|
||||||
let sectionFrame = CGRect(origin: CGPoint(x: 0.0, y: contentHeight), size: CGSize(width: layout.size.width, height: sectionHeight))
|
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 {
|
if wasAdded {
|
||||||
sectionNode.frame = sectionFrame
|
sectionNode.frame = sectionFrame
|
||||||
@ -6636,7 +6501,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.isSettings {
|
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)
|
self.scrollNode.view.contentSize = CGSize(width: layout.size.width, height: contentHeight)
|
||||||
if self.isSettings {
|
if self.isSettings {
|
||||||
@ -6646,10 +6511,6 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
self.scrollNode.view.contentOffset = 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 {
|
if additive {
|
||||||
transition.updateFrameAdditive(node: self.paneContainerNode, frame: paneContainerFrame)
|
transition.updateFrameAdditive(node: self.paneContainerNode, frame: paneContainerFrame)
|
||||||
} else {
|
} else {
|
||||||
@ -6707,12 +6568,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
} else {
|
} else {
|
||||||
sectionInset = 0.0
|
sectionInset = 0.0
|
||||||
}
|
}
|
||||||
let headerInset: CGFloat
|
let headerInset = sectionInset
|
||||||
if self.isSettings {
|
|
||||||
headerInset = sectionInset
|
|
||||||
} else {
|
|
||||||
headerInset = layout.safeInsets.left
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
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
|
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
|
let visibleHeight = self.scrollNode.view.contentOffset.y + self.scrollNode.view.bounds.height - self.paneContainerNode.frame.minY
|
||||||
|
|
||||||
var bottomInset = layout.intrinsicInsets.bottom
|
var bottomInset = layout.intrinsicInsets.bottom
|
||||||
@ -6797,18 +6649,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
private var canOpenAvatarByDragging = false
|
private var canOpenAvatarByDragging = false
|
||||||
|
|
||||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
if self.ignoreScrolling {
|
guard !self.ignoreScrolling else {
|
||||||
return
|
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.state.isEditing {
|
||||||
if self.canAddVelocity {
|
if self.canAddVelocity {
|
||||||
self.previousVelocityM1 = self.previousVelocity
|
self.previousVelocityM1 = self.previousVelocity
|
||||||
@ -6938,10 +6782,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var height: CGFloat = self.isSettings ? 140.0 : 212.0
|
let height: CGFloat = self.isSettings ? 140.0 : 140.0
|
||||||
if self.headerNode.twoLineInfo {
|
|
||||||
height += 17.0
|
|
||||||
}
|
|
||||||
if targetContentOffset.pointee.y < height {
|
if targetContentOffset.pointee.y < height {
|
||||||
if targetContentOffset.pointee.y < height / 2.0 {
|
if targetContentOffset.pointee.y < height / 2.0 {
|
||||||
targetContentOffset.pointee.y = 0.0
|
targetContentOffset.pointee.y = 0.0
|
||||||
@ -7618,12 +7459,7 @@ private final class PeerInfoNavigationTransitionNode: ASDisplayNode, CustomNavig
|
|||||||
} else {
|
} else {
|
||||||
sectionInset = 0.0
|
sectionInset = 0.0
|
||||||
}
|
}
|
||||||
let headerInset: CGFloat
|
let headerInset = sectionInset
|
||||||
if screenNode.isSettings {
|
|
||||||
headerInset = sectionInset
|
|
||||||
} else {
|
|
||||||
headerInset = layout.safeInsets.left
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
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)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ private final class PeerInfoScreenMultilineInputItemNode: PeerInfoScreenItemNode
|
|||||||
self.addSubnode(self.bottomSeparatorNode)
|
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 {
|
guard let item = item as? PeerInfoScreenMultilineInputItem else {
|
||||||
return 10.0
|
return 10.0
|
||||||
}
|
}
|
||||||
@ -101,7 +101,7 @@ private final class PeerInfoScreenMultilineInputItemNode: PeerInfoScreenItemNode
|
|||||||
separatorInset += 49.0
|
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 hasTopCorners = hasCorners && topItem == nil
|
||||||
let hasBottomCorners = hasCorners && bottomItem == nil
|
let hasBottomCorners = hasCorners && bottomItem == nil
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user