diff --git a/submodules/Display/Source/TabBarContollerNode.swift b/submodules/Display/Source/TabBarContollerNode.swift index e6f8cc21ba..e0e60803ac 100644 --- a/submodules/Display/Source/TabBarContollerNode.swift +++ b/submodules/Display/Source/TabBarContollerNode.swift @@ -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) diff --git a/submodules/Display/Source/TabBarController.swift b/submodules/Display/Source/TabBarController.swift index 68975cc378..313b2382e1 100644 --- a/submodules/Display/Source/TabBarController.swift +++ b/submodules/Display/Source/TabBarController.swift @@ -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() { diff --git a/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift b/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift index cdc0d4d559..e3ea758cfc 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/PeerAvatarImageGalleryItem.swift @@ -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)) diff --git a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenCommentItem.swift b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenCommentItem.swift index ad7c1984c3..d4de1773c7 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenCommentItem.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenCommentItem.swift @@ -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)) diff --git a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenMemberItem.swift b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenMemberItem.swift index 701e7a5389..2735847f18 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenMemberItem.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/ListItems/PeerInfoScreenMemberItem.swift @@ -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) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift index b4472b5be3..e40767c052 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoHeaderNode.swift @@ -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() 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 { diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 43775c462d..c102bf7e56 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -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) }