mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Various UI fixes
This commit is contained in:
parent
ba5d7051c4
commit
94f2cf6362
@ -74,9 +74,7 @@ final class TabBarControllerNode: ASDisplayNode {
|
||||
transition.updateAlpha(node: self.disabledOverlayNode, alpha: value ? 0.0 : 1.0)
|
||||
}
|
||||
|
||||
func updateIsTabBarHidden(_ value: Bool, transition: ContainedViewLayoutTransition) {
|
||||
transition.updateAlpha(node: self.tabBarNode, alpha: value ? 0.0 : 1.0)
|
||||
}
|
||||
var tabBarHidden = false
|
||||
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, toolbar: Toolbar?, transition: ContainedViewLayoutTransition) {
|
||||
var tabBarHeight: CGFloat
|
||||
@ -91,7 +89,7 @@ final class TabBarControllerNode: ASDisplayNode {
|
||||
tabBarHeight = 49.0 + bottomInset
|
||||
}
|
||||
|
||||
let tabBarFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - tabBarHeight), size: CGSize(width: layout.size.width, height: tabBarHeight))
|
||||
let tabBarFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - (self.tabBarHidden ? 0.0 : tabBarHeight)), size: CGSize(width: layout.size.width, height: tabBarHeight))
|
||||
|
||||
transition.updateFrame(node: self.tabBarNode, frame: tabBarFrame)
|
||||
self.tabBarNode.updateLayout(size: layout.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, bottomInset: bottomInset, transition: transition)
|
||||
|
@ -186,7 +186,10 @@ open class TabBarController: ViewController {
|
||||
}
|
||||
|
||||
public func updateIsTabBarHidden(_ value: Bool, transition: ContainedViewLayoutTransition) {
|
||||
self.tabBarControllerNode.updateIsTabBarHidden(value, transition: transition)
|
||||
self.tabBarControllerNode.tabBarHidden = value
|
||||
if let layout = self.validLayout {
|
||||
self.containerLayoutUpdated(layout, transition: .animated(duration: 0.4, curve: .slide))
|
||||
}
|
||||
}
|
||||
|
||||
override open func loadDisplayNode() {
|
||||
|
@ -225,7 +225,7 @@ final class PeerAvatarImageGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
var barButtonItems: [UIBarButtonItem] = []
|
||||
let footerContent: AvatarGalleryItemFooterContent = .info
|
||||
if self.peer.id == self.context.account.peerId {
|
||||
let rightBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Settings_EditPhoto, style: .plain, target: self, action: #selector(self.editPressed))
|
||||
let rightBarButtonItem = UIBarButtonItem(title: entry.videoRepresentations.isEmpty ? self.presentationData.strings.Settings_EditPhoto : self.presentationData.strings.Settings_EditVideo, style: .plain, target: self, action: #selector(self.editPressed))
|
||||
barButtonItems.append(rightBarButtonItem)
|
||||
}
|
||||
self._rightBarButtonItems.set(.single(barButtonItems))
|
||||
|
@ -42,7 +42,7 @@ private final class PeerInfoScreenCommentItemNode: PeerInfoScreenItemNode {
|
||||
let verticalInset: CGFloat = 7.0
|
||||
|
||||
self.textNode.maximumNumberOfLines = 0
|
||||
self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(14.0), textColor: presentationData.theme.list.freeTextColor)
|
||||
self.textNode.attributedText = NSAttributedString(string: item.text, font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize), textColor: presentationData.theme.list.freeTextColor)
|
||||
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: width - sideInset * 2.0, height: .greatestFiniteMagnitude))
|
||||
|
||||
|
@ -79,7 +79,7 @@ private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode {
|
||||
super.didLoad()
|
||||
|
||||
let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapLongTapOrDoubleTapGesture(_:)))
|
||||
recognizer.tapActionAtPoint = { [weak self] point in
|
||||
recognizer.tapActionAtPoint = { point in
|
||||
return .keepWithSingleTap
|
||||
}
|
||||
recognizer.highlight = { [weak self] point in
|
||||
@ -94,7 +94,7 @@ private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode {
|
||||
@objc private func tapLongTapOrDoubleTapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) {
|
||||
switch recognizer.state {
|
||||
case .ended:
|
||||
if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation {
|
||||
if let (gesture, _) = recognizer.lastRecognizedGestureAndLocation {
|
||||
switch gesture {
|
||||
case .tap:
|
||||
if let item = self.item {
|
||||
@ -239,7 +239,12 @@ private final class PeerInfoScreenMemberItemNode: PeerInfoScreenItemNode {
|
||||
guard let item = self.item else {
|
||||
return
|
||||
}
|
||||
if point != nil && item.context.account.peerId != item.member.id {
|
||||
var highlight = point != nil
|
||||
if case .account = item.member {
|
||||
} else if item.context.account.peerId == item.member.id {
|
||||
highlight = false
|
||||
}
|
||||
if highlight {
|
||||
self.selectionNode.updateIsHighlighted(true)
|
||||
} else {
|
||||
self.selectionNode.updateIsHighlighted(false)
|
||||
|
@ -18,6 +18,7 @@ import TelegramUniversalVideoContent
|
||||
import GalleryUI
|
||||
import UniversalMediaPlayer
|
||||
import RadialStatusNode
|
||||
import TelegramUIPreferences
|
||||
|
||||
enum PeerInfoHeaderButtonKey: Hashable {
|
||||
case message
|
||||
@ -184,10 +185,12 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode {
|
||||
|
||||
var item: PeerInfoAvatarListItem?
|
||||
|
||||
var canAttachVideo: Bool = true
|
||||
|
||||
var isExpanded: Bool = false {
|
||||
didSet {
|
||||
if let videoNode = self.videoNode, videoNode.canAttachContent != self.isExpanded {
|
||||
videoNode.canAttachContent = self.isExpanded
|
||||
videoNode.canAttachContent = self.isExpanded && self.canAttachVideo
|
||||
if videoNode.canAttachContent {
|
||||
videoNode.play()
|
||||
}
|
||||
@ -328,7 +331,7 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode {
|
||||
videoNode.updateLayout(size: imageSize, transition: .immediate)
|
||||
videoNode.frame = imageFrame
|
||||
if videoNode.canAttachContent != self.isExpanded {
|
||||
videoNode.canAttachContent = self.isExpanded
|
||||
videoNode.canAttachContent = self.isExpanded && self.canAttachVideo
|
||||
if videoNode.canAttachContent {
|
||||
videoNode.play()
|
||||
}
|
||||
@ -369,6 +372,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
private var initializedList = false
|
||||
private var ignoreNextProfilePhotoUpdate = false
|
||||
var itemsUpdated: (([PeerInfoAvatarListItem]) -> Void)?
|
||||
var currentIndexUpdated: (() -> Void)?
|
||||
|
||||
let isReady = Promise<Bool>()
|
||||
private var didSetReady = false
|
||||
@ -635,6 +639,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
|
||||
func selectFirstItem() {
|
||||
self.currentIndex = 0
|
||||
self.currentIndexUpdated?()
|
||||
if let size = self.validLayout {
|
||||
self.updateItems(size: size, transition: .immediate, stripTransition: .immediate)
|
||||
}
|
||||
@ -656,17 +661,21 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
if location.x < size.width * 1.0 / 5.0 {
|
||||
if self.currentIndex != 0 {
|
||||
self.currentIndex -= 1
|
||||
self.currentIndexUpdated?()
|
||||
self.updateItems(size: size, transition: .immediate, stripTransition: .animated(duration: 0.3, curve: .spring))
|
||||
} else if self.items.count > 1 {
|
||||
self.currentIndex = self.items.count - 1
|
||||
self.currentIndexUpdated?()
|
||||
self.updateItems(size: size, transition: .immediate, stripTransition: .animated(duration: 0.3, curve: .spring), synchronous: true)
|
||||
}
|
||||
} else {
|
||||
if self.currentIndex < self.items.count - 1 {
|
||||
self.currentIndex += 1
|
||||
self.currentIndexUpdated?()
|
||||
self.updateItems(size: size, transition: .immediate, stripTransition: .animated(duration: 0.3, curve: .spring))
|
||||
} else if self.items.count > 1 {
|
||||
self.currentIndex = 0
|
||||
self.currentIndexUpdated?()
|
||||
self.updateItems(size: size, transition: .immediate, stripTransition: .animated(duration: 0.3, curve: .spring), synchronous: true)
|
||||
}
|
||||
}
|
||||
@ -708,6 +717,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
updatedIndex = max(updatedIndex - 1, 0)
|
||||
}
|
||||
self.currentIndex = updatedIndex
|
||||
self.currentIndexUpdated?()
|
||||
self.transitionFraction = 0.0
|
||||
if let size = self.validLayout {
|
||||
self.updateItems(size: size, transition: .animated(duration: 0.3, curve: .spring), stripTransition: .animated(duration: 0.3, curve: .spring))
|
||||
@ -742,6 +752,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
self.items = items
|
||||
self.itemsUpdated?(items)
|
||||
self.currentIndex = 0
|
||||
self.currentIndexUpdated?()
|
||||
self.ignoreNextProfilePhotoUpdate = true
|
||||
if let size = self.validLayout {
|
||||
self.updateItems(size: size, update: true, transition: .immediate, stripTransition: .immediate, synchronous: true)
|
||||
@ -771,6 +782,7 @@ final class PeerInfoAvatarListContainerNode: ASDisplayNode {
|
||||
self.items = items
|
||||
self.itemsUpdated?(items)
|
||||
self.currentIndex = max(0, previousIndex - 1)
|
||||
self.currentIndexUpdated?()
|
||||
self.ignoreNextProfilePhotoUpdate = true
|
||||
if let size = self.validLayout {
|
||||
self.updateItems(size: size, update: true, transition: .immediate, stripTransition: .immediate, synchronous: true)
|
||||
@ -974,7 +986,7 @@ final class PeerInfoAvatarTransformContainerNode: ASDisplayNode {
|
||||
private var videoContent: NativeVideoContent?
|
||||
private var videoStartTimestamp: Double?
|
||||
|
||||
var canAttachVideo = true
|
||||
var canAttachVideo: Bool = true
|
||||
|
||||
var tapped: (() -> Void)?
|
||||
|
||||
@ -1449,18 +1461,20 @@ final class PeerInfoHeaderNavigationButton: HighlightableButtonNode {
|
||||
var icon: UIImage?
|
||||
var isBold = false
|
||||
switch key {
|
||||
case .edit:
|
||||
text = presentationData.strings.Common_Edit
|
||||
case .done, .cancel, .selectionDone:
|
||||
text = presentationData.strings.Common_Done
|
||||
isBold = true
|
||||
case .select:
|
||||
text = presentationData.strings.Common_Select
|
||||
case .search:
|
||||
text = ""
|
||||
icon = PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme)
|
||||
case .editPhoto:
|
||||
text = presentationData.strings.Settings_EditPhoto
|
||||
case .edit:
|
||||
text = presentationData.strings.Common_Edit
|
||||
case .done, .cancel, .selectionDone:
|
||||
text = presentationData.strings.Common_Done
|
||||
isBold = true
|
||||
case .select:
|
||||
text = presentationData.strings.Common_Select
|
||||
case .search:
|
||||
text = ""
|
||||
icon = PresentationResourcesRootController.navigationCompactSearchIcon(presentationData.theme)
|
||||
case .editPhoto:
|
||||
text = presentationData.strings.Settings_EditPhoto
|
||||
case .editVideo:
|
||||
text = presentationData.strings.Settings_EditVideo
|
||||
}
|
||||
|
||||
let font: UIFont = isBold ? Font.semibold(17.0) : Font.regular(17.0)
|
||||
@ -1499,6 +1513,7 @@ enum PeerInfoHeaderNavigationButtonKey {
|
||||
case selectionDone
|
||||
case search
|
||||
case editPhoto
|
||||
case editVideo
|
||||
}
|
||||
|
||||
struct PeerInfoHeaderNavigationButtonSpec: Equatable {
|
||||
@ -1596,7 +1611,13 @@ final class PeerInfoHeaderNavigationButtonContainerNode: ASDisplayNode {
|
||||
}
|
||||
transition.updateFrameAdditiveToCenter(node: buttonNode, frame: buttonFrame)
|
||||
let alphaFactor: CGFloat = spec.isForExpandedView ? expandFraction : (1.0 - expandFraction)
|
||||
transition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||
|
||||
|
||||
var buttonTransition = transition
|
||||
if case let .animated(duration, curve) = buttonTransition, alphaFactor == 0.0 {
|
||||
buttonTransition = .animated(duration: duration * 0.25, curve: curve)
|
||||
}
|
||||
buttonTransition.updateAlpha(node: buttonNode, alpha: alphaFactor * alphaFactor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1622,6 +1643,7 @@ protocol PeerInfoHeaderTextFieldNode: ASDisplayNode {
|
||||
|
||||
final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode, UITextFieldDelegate {
|
||||
private let textNode: TextFieldNode
|
||||
private let measureTextNode: ImmediateTextNode
|
||||
private let clearIconNode: ASImageNode
|
||||
private let clearButtonNode: HighlightableButtonNode
|
||||
private let topSeparator: ASDisplayNode
|
||||
@ -1634,6 +1656,8 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
|
||||
|
||||
override init() {
|
||||
self.textNode = TextFieldNode()
|
||||
self.measureTextNode = ImmediateTextNode()
|
||||
self.measureTextNode.maximumNumberOfLines = 0
|
||||
|
||||
self.clearIconNode = ASImageNode()
|
||||
self.clearIconNode.isLayerBacked = true
|
||||
@ -1690,6 +1714,9 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
|
||||
}
|
||||
|
||||
func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat {
|
||||
let titleFont = Font.regular(presentationData.listsFontSize.itemListBaseFontSize)
|
||||
self.textNode.textField.font = titleFont
|
||||
|
||||
if self.theme !== presentationData.theme {
|
||||
self.theme = presentationData.theme
|
||||
self.textNode.textField.textColor = presentationData.theme.list.itemPrimaryTextColor
|
||||
@ -1699,7 +1726,7 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
|
||||
self.clearIconNode.image = PresentationResourcesItemList.itemListClearInputIcon(presentationData.theme)
|
||||
}
|
||||
|
||||
let attributedPlaceholderText = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: presentationData.theme.list.itemPlaceholderTextColor)
|
||||
let attributedPlaceholderText = NSAttributedString(string: placeholder, font: titleFont, textColor: presentationData.theme.list.itemPlaceholderTextColor)
|
||||
if self.textNode.textField.attributedPlaceholder == nil || !self.textNode.textField.attributedPlaceholder!.isEqual(to: attributedPlaceholderText) {
|
||||
self.textNode.textField.attributedPlaceholder = attributedPlaceholderText
|
||||
self.textNode.textField.accessibilityHint = attributedPlaceholderText.string
|
||||
@ -1712,7 +1739,12 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader
|
||||
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 height: CGFloat = 44.0
|
||||
let measureText = "|"
|
||||
let attributedMeasureText = NSAttributedString(string: measureText, font: titleFont, textColor: .black)
|
||||
self.measureTextNode.attributedText = attributedMeasureText
|
||||
let measureTextSize = self.measureTextNode.updateLayout(CGSize(width: width - safeInset * 2.0 - 16.0 * 2.0 - 38.0, height: .greatestFiniteMagnitude))
|
||||
|
||||
let height = measureTextSize.height + 22.0
|
||||
|
||||
let buttonSize = CGSize(width: 38.0, height: height)
|
||||
self.clearButtonNode.frame = CGRect(origin: CGPoint(x: width - safeInset - buttonSize.width, y: 0.0), size: buttonSize)
|
||||
@ -1739,6 +1771,7 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
|
||||
|
||||
private let requestUpdateHeight: () -> Void
|
||||
|
||||
private var fontSize: PresentationFontSize?
|
||||
private var theme: PresentationTheme?
|
||||
private var currentParams: (width: CGFloat, safeInset: CGFloat)?
|
||||
private var currentMeasuredHeight: CGFloat?
|
||||
@ -1795,7 +1828,13 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
|
||||
guard let theme = self.theme else {
|
||||
return
|
||||
}
|
||||
let attributedText = NSAttributedString(string: "", font: Font.regular(17.0), textColor: theme.list.itemPrimaryTextColor)
|
||||
let font: UIFont
|
||||
if let fontSize = self.fontSize {
|
||||
font = Font.regular(fontSize.itemListBaseFontSize)
|
||||
} else {
|
||||
font = Font.regular(17.0)
|
||||
}
|
||||
let attributedText = NSAttributedString(string: "", font: font, textColor: theme.list.itemPrimaryTextColor)
|
||||
self.textNode.attributedText = attributedText
|
||||
self.requestUpdateHeight()
|
||||
self.updateClearButtonVisibility()
|
||||
@ -1804,11 +1843,14 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
|
||||
func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat {
|
||||
self.currentParams = (width, safeInset)
|
||||
|
||||
self.fontSize = presentationData.listsFontSize
|
||||
let titleFont = Font.regular(presentationData.listsFontSize.itemListBaseFontSize)
|
||||
|
||||
if self.theme !== presentationData.theme {
|
||||
self.theme = presentationData.theme
|
||||
let textColor = presentationData.theme.list.itemPrimaryTextColor
|
||||
|
||||
self.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: textColor]
|
||||
self.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: titleFont, NSAttributedString.Key.foregroundColor.rawValue: textColor]
|
||||
|
||||
self.textNode.clipsToBounds = true
|
||||
self.textNode.delegate = self
|
||||
@ -1820,13 +1862,13 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
|
||||
self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor
|
||||
self.topSeparator.frame = CGRect(origin: CGPoint(x: safeInset + (hasPrevious ? 16.0 : 0.0), y: 0.0), size: CGSize(width: width, height: UIScreenPixel))
|
||||
|
||||
let attributedPlaceholderText = NSAttributedString(string: placeholder, font: Font.regular(17.0), 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) {
|
||||
self.textNode.attributedPlaceholderText = attributedPlaceholderText
|
||||
}
|
||||
|
||||
if let updateText = updateText {
|
||||
let attributedText = NSAttributedString(string: updateText, font: Font.regular(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||
let attributedText = NSAttributedString(string: updateText, font: titleFont, textColor: presentationData.theme.list.itemPrimaryTextColor)
|
||||
self.textNode.attributedText = attributedText
|
||||
}
|
||||
|
||||
@ -1834,7 +1876,7 @@ final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderT
|
||||
if measureText.hasSuffix("\n") || measureText.isEmpty {
|
||||
measureText += "|"
|
||||
}
|
||||
let attributedMeasureText = NSAttributedString(string: measureText, font: Font.regular(17.0), textColor: .black)
|
||||
let attributedMeasureText = NSAttributedString(string: measureText, font: titleFont, textColor: .black)
|
||||
self.measureTextNode.attributedText = attributedMeasureText
|
||||
let measureTextSize = self.measureTextNode.updateLayout(CGSize(width: width - safeInset * 2.0 - 16.0 * 2.0 - 38.0, height: .greatestFiniteMagnitude))
|
||||
self.currentMeasuredHeight = measureTextSize.height
|
||||
@ -2104,6 +2146,8 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
var requestOpenAvatarForEditing: ((Bool) -> Void)?
|
||||
var requestUpdateLayout: (() -> Void)?
|
||||
|
||||
var displayCopyContextMenu: ((ASDisplayNode, Bool, Bool) -> Void)?
|
||||
|
||||
var navigationTransition: PeerInfoHeaderNavigationTransition?
|
||||
|
||||
init(context: AccountContext, avatarInitiallyExpanded: Bool, isOpenedFromChat: Bool, isSettings: Bool) {
|
||||
@ -2134,13 +2178,11 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
self.subtitleNodeRawContainer = ASDisplayNode()
|
||||
self.subtitleNode = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
|
||||
self.subtitleNode.displaysAsynchronously = false
|
||||
self.subtitleNode.allowsGroupOpacity = true
|
||||
|
||||
self.usernameNodeContainer = ASDisplayNode()
|
||||
self.usernameNodeRawContainer = ASDisplayNode()
|
||||
self.usernameNode = MultiScaleTextNode(stateKeys: [TitleNodeStateRegular, TitleNodeStateExpanded])
|
||||
self.usernameNode.displaysAsynchronously = false
|
||||
self.usernameNode.allowsGroupOpacity = true
|
||||
|
||||
self.regularContentNode = PeerInfoHeaderRegularContentNode()
|
||||
var requestUpdateLayoutImpl: (() -> Void)?
|
||||
@ -2173,8 +2215,10 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
self.regularContentNode.addSubnode(self.titleNodeContainer)
|
||||
self.subtitleNodeContainer.addSubnode(self.subtitleNode)
|
||||
self.regularContentNode.addSubnode(self.subtitleNodeContainer)
|
||||
self.regularContentNode.addSubnode(self.subtitleNodeRawContainer)
|
||||
self.usernameNodeContainer.addSubnode(self.usernameNode)
|
||||
self.regularContentNode.addSubnode(self.usernameNodeContainer)
|
||||
self.regularContentNode.addSubnode(self.usernameNodeRawContainer)
|
||||
self.regularContentNode.addSubnode(self.avatarListNode)
|
||||
self.regularContentNode.addSubnode(self.avatarListNode.listContainerNode.controlsClippingOffsetNode)
|
||||
self.addSubnode(self.regularContentNode)
|
||||
@ -2194,6 +2238,28 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
let usernameGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleUsernameLongPress(_:)))
|
||||
self.usernameNodeRawContainer.view.addGestureRecognizer(usernameGestureRecognizer)
|
||||
|
||||
let phoneGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handlePhoneLongPress(_:)))
|
||||
self.subtitleNodeRawContainer.view.addGestureRecognizer(phoneGestureRecognizer)
|
||||
}
|
||||
|
||||
@objc private func handleUsernameLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
|
||||
if gestureRecognizer.state == .began {
|
||||
self.displayCopyContextMenu?(self.usernameNodeRawContainer, !self.isAvatarExpanded, true)
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func handlePhoneLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) {
|
||||
if gestureRecognizer.state == .began {
|
||||
self.displayCopyContextMenu?(self.subtitleNodeRawContainer, true, !self.isAvatarExpanded)
|
||||
}
|
||||
}
|
||||
|
||||
func initiateAvatarExpansion() {
|
||||
if self.isAvatarExpanded {
|
||||
if let currentEntry = self.avatarListNode.listContainerNode.currentEntry {
|
||||
|
@ -2465,7 +2465,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
strongSelf.paneContainerNode.updateSelectedMessageIds(strongSelf.state.selectedMessageIds, animated: true)
|
||||
case .search:
|
||||
strongSelf.activateSearch()
|
||||
case .editPhoto:
|
||||
case .editPhoto, .editVideo:
|
||||
strongSelf.openAvatarOptions()
|
||||
}
|
||||
}
|
||||
@ -2503,10 +2503,41 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
self.cachedFaq.set(.single(nil) |> then(cachedFaqInstantPage(context: self.context) |> map(Optional.init)))
|
||||
|
||||
screenData = peerInfoScreenSettingsData(context: context, peerId: peerId, accountsAndPeers: self.accountsAndPeers.get(), activeSessionsContextAndCount: self.activeSessionsContextAndCount.get(), notificationExceptions: self.notificationExceptions.get(), privacySettings: self.privacySettings.get(), archivedStickerPacks: self.archivedPacks.get(), hasPassport: self.hasPassport.get())
|
||||
|
||||
self.headerNode.displayCopyContextMenu = { [weak self] node, copyPhone, copyUsername in
|
||||
guard let strongSelf = self, let data = strongSelf.data, let user = data.peer as? TelegramUser else {
|
||||
return
|
||||
}
|
||||
var actions: [ContextMenuAction] = []
|
||||
if copyPhone, let phone = user.phone, !phone.isEmpty {
|
||||
actions.append(ContextMenuAction(content: .text(title: strongSelf.presentationData.strings.Settings_CopyPhoneNumber, accessibilityLabel: strongSelf.presentationData.strings.Settings_CopyPhoneNumber), action: {
|
||||
UIPasteboard.general.string = formatPhoneNumber(phone)
|
||||
}))
|
||||
}
|
||||
|
||||
if copyUsername, let username = user.username, !username.isEmpty {
|
||||
actions.append(ContextMenuAction(content: .text(title: strongSelf.presentationData.strings.Settings_CopyUsername, accessibilityLabel: strongSelf.presentationData.strings.Settings_CopyUsername), action: {
|
||||
UIPasteboard.general.string = username
|
||||
}))
|
||||
}
|
||||
|
||||
let contextMenuController = ContextMenuController(actions: actions)
|
||||
strongSelf.controller?.present(contextMenuController, in: .window(.root), with: ContextMenuControllerPresentationArguments(sourceNodeAndRect: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
return (node, node.bounds.insetBy(dx: 0.0, dy: -2.0), strongSelf, strongSelf.view.bounds)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
screenData = peerInfoScreenData(context: context, peerId: peerId, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, isSettings: self.isSettings, ignoreGroupInCommon: ignoreGroupInCommon)
|
||||
}
|
||||
|
||||
self.headerNode.avatarListNode.listContainerNode.currentIndexUpdated = { [weak self] in
|
||||
self?.updateNavigation(transition: .immediate, additive: false)
|
||||
}
|
||||
|
||||
self.dataDisposable = (screenData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] data in
|
||||
guard let strongSelf = self else {
|
||||
@ -2554,9 +2585,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
self.preloadStickerDisposable.dispose()
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
}
|
||||
var canAttachVideo: Bool?
|
||||
|
||||
private func updateData(_ data: PeerInfoScreenData) {
|
||||
let previousData = self.data
|
||||
@ -5230,7 +5259,11 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
} else {
|
||||
if self.isSettings {
|
||||
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: false))
|
||||
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .editPhoto, isForExpandedView: true))
|
||||
if let item = self.headerNode.avatarListNode.listContainerNode.currentItemNode?.item, case let .image(image) = item, !image.2.isEmpty {
|
||||
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .editVideo, isForExpandedView: true))
|
||||
} else {
|
||||
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .editPhoto, isForExpandedView: true))
|
||||
}
|
||||
} else if peerInfoCanEdit(peer: self.data?.peer, cachedData: self.data?.cachedData) {
|
||||
navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .edit, isForExpandedView: false))
|
||||
}
|
||||
@ -5303,7 +5336,14 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
self.hapticFeedback?.impact()
|
||||
|
||||
self.canOpenAvatarByDragging = false
|
||||
let contentOffset = scrollView.contentOffset.y
|
||||
scrollView.panGestureRecognizer.isEnabled = false
|
||||
self.headerNode.initiateAvatarExpansion()
|
||||
scrollView.panGestureRecognizer.isEnabled = true
|
||||
scrollView.contentOffset = CGPoint(x: 0.0, y: contentOffset)
|
||||
UIView.animate(withDuration: 0.1) {
|
||||
scrollView.contentOffset = CGPoint()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if offsetY >= 1.0 {
|
||||
@ -5719,10 +5759,18 @@ public final class PeerInfoScreen: ViewController {
|
||||
|
||||
super.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
public override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
self.controllerNode.canAttachVideo = false
|
||||
}
|
||||
|
||||
override public func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
|
||||
self.controllerNode.canAttachVideo = true
|
||||
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.controllerNode.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user