diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index f80c4933a0..e2a58bc517 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -3203,8 +3203,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G media = .keep } - strongSelf.editMessageDisposable.set((requestEditMessage(account: strongSelf.context.account, messageId: editMessage.messageId, text: text.string, media: media - , entities: entitiesAttribute, disableUrlPreview: disableUrlPreview) |> deliverOnMainQueue |> afterDisposed({ + strongSelf.editMessageDisposable.set((requestEditMessage(account: strongSelf.context.account, messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, disableUrlPreview: disableUrlPreview) |> deliverOnMainQueue |> afterDisposed({ editingMessage.set(nil) })).start(next: { result in guard let strongSelf = self else { @@ -4120,15 +4119,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.slowmodeTooltipController = slowmodeTooltipController strongSelf.window?.presentInGlobalOverlay(slowmodeTooltipController) - }, displaySendMessageOptions: { [weak self] in - if let strongSelf = self, let sendButtonFrame = strongSelf.chatDisplayNode.sendButtonFrame(), let textInputNode = strongSelf.chatDisplayNode.textInputNode(), let layout = strongSelf.validLayout { + }, displaySendMessageOptions: { [weak self] node, gesture in + if let strongSelf = self, let textInputNode = strongSelf.chatDisplayNode.textInputNode(), let layout = strongSelf.validLayout { if layout.size.width > layout.size.height { strongSelf.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .landscape) } else { strongSelf.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) } - let controller = ChatSendMessageActionSheetController(context: strongSelf.context, controllerInteraction: strongSelf.controllerInteraction, interfaceState: strongSelf.presentationInterfaceState, sendButtonFrame: strongSelf.chatDisplayNode.convert(sendButtonFrame, to: nil), textInputNode: textInputNode, completion: { [weak self] in + let controller = ChatSendMessageActionSheetController(context: strongSelf.context, controllerInteraction: strongSelf.controllerInteraction, interfaceState: strongSelf.presentationInterfaceState, gesture: gesture, sendButtonFrame: node.view.convert(node.bounds, to: nil), textInputNode: textInputNode, completion: { [weak self] in if let strongSelf = self { strongSelf.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .all) } diff --git a/submodules/TelegramUI/TelegramUI/ChatPanelInterfaceInteraction.swift b/submodules/TelegramUI/TelegramUI/ChatPanelInterfaceInteraction.swift index 47c6496061..7aa8bd50b5 100644 --- a/submodules/TelegramUI/TelegramUI/ChatPanelInterfaceInteraction.swift +++ b/submodules/TelegramUI/TelegramUI/ChatPanelInterfaceInteraction.swift @@ -111,12 +111,12 @@ final class ChatPanelInterfaceInteraction { let openLinkEditing: () -> Void let reportPeerIrrelevantGeoLocation: () -> Void let displaySlowmodeTooltip: (ASDisplayNode, CGRect) -> Void - let displaySendMessageOptions: () -> Void + let displaySendMessageOptions: (ASDisplayNode, ContextGesture) -> Void let openScheduledMessages: () -> Void let displaySearchResultsTooltip: (ASDisplayNode, CGRect) -> Void let statuses: ChatPanelInterfaceInteractionStatuses? - init(setupReplyMessage: @escaping (MessageId, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void, deleteSelectedMessages: @escaping () -> Void, reportSelectedMessages: @escaping () -> Void, reportMessages: @escaping ([Message], ContextController?) -> Void, deleteMessages: @escaping ([Message], ContextController?, @escaping (ContextMenuActionResult) -> Void) -> Void, forwardSelectedMessages: @escaping () -> Void, forwardCurrentForwardMessages: @escaping () -> Void, forwardMessages: @escaping ([Message]) -> Void, shareSelectedMessages: @escaping () -> Void, updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, openStickers: @escaping () -> Void, editMessage: @escaping () -> Void, beginMessageSearch: @escaping (ChatSearchDomain, String) -> Void, dismissMessageSearch: @escaping () -> Void, updateMessageSearch: @escaping (String) -> Void, openSearchResults: @escaping () -> Void, navigateMessageSearch: @escaping (ChatPanelSearchNavigationAction) -> Void, openCalendarSearch: @escaping () -> Void, toggleMembersSearch: @escaping (Bool) -> Void, navigateToMessage: @escaping (MessageId) -> Void, navigateToChat: @escaping (PeerId) -> Void, openPeerInfo: @escaping () -> Void, togglePeerNotifications: @escaping () -> Void, sendContextResult: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, sendBotCommand: @escaping (Peer, String) -> Void, sendBotStart: @escaping (String?) -> Void, botSwitchChatWithPayload: @escaping (PeerId, String) -> Void, beginMediaRecording: @escaping (Bool) -> Void, finishMediaRecording: @escaping (ChatFinishMediaRecordingAction) -> Void, stopMediaRecording: @escaping () -> Void, lockMediaRecording: @escaping () -> Void, deleteRecordedMedia: @escaping () -> Void, sendRecordedMedia: @escaping () -> Void, displayRestrictedInfo: @escaping (ChatPanelRestrictionInfoSubject, ChatPanelRestrictionInfoDisplayType) -> Void, displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId) -> Void, unpinMessage: @escaping () -> Void, shareAccountContact: @escaping () -> Void, reportPeer: @escaping () -> Void, presentPeerContact: @escaping () -> Void, dismissReportPeer: @escaping () -> Void, deleteChat: @escaping () -> Void, beginCall: @escaping () -> Void, toggleMessageStickerStarred: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, navigateFeed: @escaping () -> Void, openGrouping: @escaping () -> Void, toggleSilentPost: @escaping () -> Void, requestUnvoteInMessage: @escaping (MessageId) -> Void, requestStopPollInMessage: @escaping (MessageId) -> Void, updateInputLanguage: @escaping ((String?) -> String?) -> Void, unarchiveChat: @escaping () -> Void, openLinkEditing: @escaping () -> Void, reportPeerIrrelevantGeoLocation: @escaping () -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, displaySendMessageOptions: @escaping () -> Void, openScheduledMessages: @escaping () -> Void, displaySearchResultsTooltip: @escaping (ASDisplayNode, CGRect) -> Void, statuses: ChatPanelInterfaceInteractionStatuses?) { + init(setupReplyMessage: @escaping (MessageId, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, setupEditMessage: @escaping (MessageId?, @escaping (ContainedViewLayoutTransition) -> Void) -> Void, beginMessageSelection: @escaping ([MessageId], @escaping (ContainedViewLayoutTransition) -> Void) -> Void, deleteSelectedMessages: @escaping () -> Void, reportSelectedMessages: @escaping () -> Void, reportMessages: @escaping ([Message], ContextController?) -> Void, deleteMessages: @escaping ([Message], ContextController?, @escaping (ContextMenuActionResult) -> Void) -> Void, forwardSelectedMessages: @escaping () -> Void, forwardCurrentForwardMessages: @escaping () -> Void, forwardMessages: @escaping ([Message]) -> Void, shareSelectedMessages: @escaping () -> Void, updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void, updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void, openStickers: @escaping () -> Void, editMessage: @escaping () -> Void, beginMessageSearch: @escaping (ChatSearchDomain, String) -> Void, dismissMessageSearch: @escaping () -> Void, updateMessageSearch: @escaping (String) -> Void, openSearchResults: @escaping () -> Void, navigateMessageSearch: @escaping (ChatPanelSearchNavigationAction) -> Void, openCalendarSearch: @escaping () -> Void, toggleMembersSearch: @escaping (Bool) -> Void, navigateToMessage: @escaping (MessageId) -> Void, navigateToChat: @escaping (PeerId) -> Void, openPeerInfo: @escaping () -> Void, togglePeerNotifications: @escaping () -> Void, sendContextResult: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, sendBotCommand: @escaping (Peer, String) -> Void, sendBotStart: @escaping (String?) -> Void, botSwitchChatWithPayload: @escaping (PeerId, String) -> Void, beginMediaRecording: @escaping (Bool) -> Void, finishMediaRecording: @escaping (ChatFinishMediaRecordingAction) -> Void, stopMediaRecording: @escaping () -> Void, lockMediaRecording: @escaping () -> Void, deleteRecordedMedia: @escaping () -> Void, sendRecordedMedia: @escaping () -> Void, displayRestrictedInfo: @escaping (ChatPanelRestrictionInfoSubject, ChatPanelRestrictionInfoDisplayType) -> Void, displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, sendSticker: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId) -> Void, unpinMessage: @escaping () -> Void, shareAccountContact: @escaping () -> Void, reportPeer: @escaping () -> Void, presentPeerContact: @escaping () -> Void, dismissReportPeer: @escaping () -> Void, deleteChat: @escaping () -> Void, beginCall: @escaping () -> Void, toggleMessageStickerStarred: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: @escaping () -> NavigationController?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, navigateFeed: @escaping () -> Void, openGrouping: @escaping () -> Void, toggleSilentPost: @escaping () -> Void, requestUnvoteInMessage: @escaping (MessageId) -> Void, requestStopPollInMessage: @escaping (MessageId) -> Void, updateInputLanguage: @escaping ((String?) -> String?) -> Void, unarchiveChat: @escaping () -> Void, openLinkEditing: @escaping () -> Void, reportPeerIrrelevantGeoLocation: @escaping () -> Void, displaySlowmodeTooltip: @escaping (ASDisplayNode, CGRect) -> Void, displaySendMessageOptions: @escaping (ASDisplayNode, ContextGesture) -> Void, openScheduledMessages: @escaping () -> Void, displaySearchResultsTooltip: @escaping (ASDisplayNode, CGRect) -> Void, statuses: ChatPanelInterfaceInteractionStatuses?) { self.setupReplyMessage = setupReplyMessage self.setupEditMessage = setupEditMessage self.beginMessageSelection = beginMessageSelection diff --git a/submodules/TelegramUI/TelegramUI/ChatRecentActionsController.swift b/submodules/TelegramUI/TelegramUI/ChatRecentActionsController.swift index 472b19bd5a..9505a0ac16 100644 --- a/submodules/TelegramUI/TelegramUI/ChatRecentActionsController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatRecentActionsController.swift @@ -112,7 +112,7 @@ final class ChatRecentActionsController: TelegramBaseController { }, openLinkEditing: { }, reportPeerIrrelevantGeoLocation: { }, displaySlowmodeTooltip: { _, _ in - }, displaySendMessageOptions: { + }, displaySendMessageOptions: { _, _ in }, openScheduledMessages: { }, displaySearchResultsTooltip: { _, _ in }, statuses: nil) diff --git a/submodules/TelegramUI/TelegramUI/ChatRecordingPreviewInputPanelNode.swift b/submodules/TelegramUI/TelegramUI/ChatRecordingPreviewInputPanelNode.swift index d2b2509ad3..b1279dc1bd 100644 --- a/submodules/TelegramUI/TelegramUI/ChatRecordingPreviewInputPanelNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatRecordingPreviewInputPanelNode.swift @@ -9,6 +9,7 @@ import SwiftSignalKit import TelegramPresentationData import UniversalMediaPlayer import AppBundle +import ContextUI private func generatePauseIcon(_ theme: PresentationTheme) -> UIImage? { return generateTintedImage(image: UIImage(bundleImageName: "GlobalMusicPlayer/MinimizedPause"), color: theme.chat.inputPanel.actionControlForegroundColor) @@ -38,6 +39,8 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode { private let statusDisposable = MetaDisposable() + private var gestureRecognizer: ContextGesture? + init(theme: PresentationTheme) { self.deleteButton = HighlightableButtonNode() self.deleteButton.displaysAsynchronously = false @@ -112,18 +115,18 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode { override func didLoad() { super.didLoad() - let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress(_:))) - gestureRecognizer.minimumPressDuration = 0.4 + let gestureRecognizer = ContextGesture(target: nil, action: nil) self.sendButton.view.addGestureRecognizer(gestureRecognizer) - } - - @objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) { - if gestureRecognizer.state == .began { - self.interfaceInteraction?.displaySendMessageOptions() + self.gestureRecognizer = gestureRecognizer + gestureRecognizer.activated = { [weak self] gesture in + guard let strongSelf = self else { + return + } + strongSelf.interfaceInteraction?.displaySendMessageOptions(strongSelf.sendButton, gesture) } } - override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics) -> CGFloat { if self.presentationInterfaceState != interfaceState { var updateWaveform = false if self.presentationInterfaceState?.recordedMediaPreview != interfaceState.recordedMediaPreview { diff --git a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetController.swift b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetController.swift index ea44a0a7bc..b3dc91fb9b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetController.swift @@ -5,6 +5,7 @@ import AsyncDisplayKit import SwiftSignalKit import TelegramPresentationData import AccountContext +import ContextUI final class ChatSendMessageActionSheetController: ViewController { var controllerNode: ChatSendMessageActionSheetControllerNode { @@ -14,6 +15,7 @@ final class ChatSendMessageActionSheetController: ViewController { private let context: AccountContext private let controllerInteraction: ChatControllerInteraction? private let interfaceState: ChatPresentationInterfaceState + private let gesture: ContextGesture private let sendButtonFrame: CGRect private let textInputNode: EditableTextNode private let completion: () -> Void @@ -26,10 +28,11 @@ final class ChatSendMessageActionSheetController: ViewController { private let hapticFeedback = HapticFeedback() - init(context: AccountContext, controllerInteraction: ChatControllerInteraction?, interfaceState: ChatPresentationInterfaceState, sendButtonFrame: CGRect, textInputNode: EditableTextNode, completion: @escaping () -> Void) { + init(context: AccountContext, controllerInteraction: ChatControllerInteraction?, interfaceState: ChatPresentationInterfaceState, gesture: ContextGesture, sendButtonFrame: CGRect, textInputNode: EditableTextNode, completion: @escaping () -> Void) { self.context = context self.controllerInteraction = controllerInteraction self.interfaceState = interfaceState + self.gesture = gesture self.sendButtonFrame = sendButtonFrame self.textInputNode = textInputNode self.completion = completion @@ -68,7 +71,7 @@ final class ChatSendMessageActionSheetController: ViewController { reminders = true } - self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, reminders: reminders, sendButtonFrame: self.sendButtonFrame, textInputNode: self.textInputNode, forwardedCount: forwardedCount, send: { [weak self] in + self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, reminders: reminders, gesture: gesture, sendButtonFrame: self.sendButtonFrame, textInputNode: self.textInputNode, forwardedCount: forwardedCount, send: { [weak self] in self?.controllerInteraction?.sendCurrentMessage(false) self?.dismiss(cancel: false) }, sendSilently: { [weak self] in @@ -107,6 +110,7 @@ final class ChatSendMessageActionSheetController: ViewController { } private func dismiss(cancel: Bool) { + self.statusBar.statusBarStyle = .Ignore self.controllerNode.animateOut(cancel: cancel, completion: { [weak self] in self?.completion() self?.didPlayPresentationAnimation = false diff --git a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift index 8b9b07248d..57f0404d0b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift @@ -9,6 +9,7 @@ import SyncCore import TelegramPresentationData import AccountContext import AppBundle +import ContextUI private let leftInset: CGFloat = 16.0 private let rightInset: CGFloat = 16.0 @@ -32,7 +33,7 @@ private enum ChatSendMessageActionIcon { private final class ActionSheetItemNode: ASDisplayNode { private let title: String private let icon: ChatSendMessageActionIcon - private let action: () -> Void + let action: () -> Void private let separatorNode: ASDisplayNode private let backgroundNode: ASDisplayNode @@ -92,13 +93,23 @@ private final class ActionSheetItemNode: ASDisplayNode { self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) self.buttonNode.highligthedChanged = { [weak self] highlighted in if let strongSelf = self { - if highlighted { - strongSelf.highlightedBackgroundNode.layer.removeAnimation(forKey: "opacity") - strongSelf.highlightedBackgroundNode.alpha = 1.0 - } else { - strongSelf.highlightedBackgroundNode.alpha = 0.0 - strongSelf.highlightedBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3) - } + strongSelf.setHighlighted(highlighted, animated: true) + } + } + } + + func setHighlighted(_ highlighted: Bool, animated: Bool) { + if highlighted == (self.highlightedBackgroundNode.alpha == 1.0) { + return + } + + if highlighted { + self.highlightedBackgroundNode.layer.removeAnimation(forKey: "opacity") + self.highlightedBackgroundNode.alpha = 1.0 + } else { + self.highlightedBackgroundNode.alpha = 0.0 + if animated { + self.highlightedBackgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3) } } } @@ -170,7 +181,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, private var validLayout: ContainerViewLayout? - init(context: AccountContext, reminders: Bool, sendButtonFrame: CGRect, textInputNode: EditableTextNode, forwardedCount: Int?, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { + init(context: AccountContext, reminders: Bool, gesture: ContextGesture, sendButtonFrame: CGRect, textInputNode: EditableTextNode, forwardedCount: Int?, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { self.context = context self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.sendButtonFrame = sendButtonFrame @@ -280,6 +291,38 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, } self.contentNodes.forEach(self.contentContainerNode.addSubnode) + + gesture.externalUpdated = { [weak self] view, location in + guard let strongSelf = self else { + return + } + for contentNode in strongSelf.contentNodes { + let localPoint = contentNode.view.convert(location, from: view) + if contentNode.bounds.contains(localPoint) { + contentNode.setHighlighted(true, animated: false) + } else { + contentNode.setHighlighted(false, animated: false) + } + } + } + + gesture.externalEnded = { [weak self] viewAndLocation in + guard let strongSelf = self else { + return + } + for contentNode in strongSelf.contentNodes { + if let (view, location) = viewAndLocation { + let localPoint = contentNode.view.convert(location, from: view) + if contentNode.bounds.contains(localPoint) { + contentNode.action() + } else { + contentNode.setHighlighted(false, animated: false) + } + } else { + contentNode.setHighlighted(false, animated: false) + } + } + } } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { @@ -395,11 +438,13 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, } self.fromMessageTextNode.layer.animatePosition(from: CGPoint(x: textXOffset, y: delta * 2.0 + textYOffset), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true) self.toMessageTextNode.layer.animatePosition(from: CGPoint(x: textXOffset, y: delta * 2.0 + textYOffset), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + + let contentOffset = CGPoint(x: self.sendButtonFrame.midX - self.contentContainerNode.frame.midX, y: self.sendButtonFrame.midY - self.contentContainerNode.frame.midY) let springDuration: Double = 0.42 let springDamping: CGFloat = 104.0 self.contentContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping) - self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: 160.0, y: 0.0)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true) + self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true) } } @@ -499,8 +544,10 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, completedBubble = true } - self.contentContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 160.0, y: 0.0), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true) - self.contentContainerNode.layer.animateScale(from: 1.0, to: 0.4, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) + let contentOffset = CGPoint(x: self.sendButtonFrame.midX - self.contentContainerNode.frame.midX, y: self.sendButtonFrame.midY - self.contentContainerNode.frame.midY) + + self.contentContainerNode.layer.animatePosition(from: CGPoint(), to: contentOffset, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true) + self.contentContainerNode.layer.animateScale(from: 1.0, to: 0.1, duration: duration, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatTextInputActionButtonsNode.swift b/submodules/TelegramUI/TelegramUI/ChatTextInputActionButtonsNode.swift index 9aebf3c921..da2860a01a 100644 --- a/submodules/TelegramUI/TelegramUI/ChatTextInputActionButtonsNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatTextInputActionButtonsNode.swift @@ -3,20 +3,21 @@ import UIKit import AsyncDisplayKit import Display import TelegramPresentationData +import ContextUI final class ChatTextInputActionButtonsNode: ASDisplayNode { private let strings: PresentationStrings let micButton: ChatTextInputMediaRecordingButton - let sendButton: HighlightTrackingButton + let sendButton: HighlightTrackingButtonNode var sendButtonRadialStatusNode: ChatSendButtonRadialStatusNode? var sendButtonHasApplyIcon = false var animatingSendButton = false let expandMediaInputButton: HighlightableButtonNode - var sendButtonLongPressed: (() -> Void)? + var sendButtonLongPressed: ((ASDisplayNode, ContextGesture) -> Void)? - private var gestureRecognizer: UILongPressGestureRecognizer? + private var gestureRecognizer: ContextGesture? var sendButtonLongPressEnabled = false { didSet { self.gestureRecognizer?.isEnabled = self.sendButtonLongPressEnabled @@ -27,9 +28,9 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode { self.strings = strings self.micButton = ChatTextInputMediaRecordingButton(theme: theme, presentController: presentController) - self.sendButton = HighlightTrackingButton() - self.sendButton.adjustsImageWhenHighlighted = false - self.sendButton.adjustsImageWhenDisabled = false + self.sendButton = HighlightTrackingButtonNode() + //self.sendButton.adjustsImageWhenHighlighted = false + //self.sendButton.adjustsImageWhenDisabled = false self.expandMediaInputButton = HighlightableButtonNode() @@ -59,22 +60,29 @@ final class ChatTextInputActionButtonsNode: ASDisplayNode { } self.view.addSubview(self.micButton) - self.view.addSubview(self.sendButton) + self.addSubnode(self.sendButton) self.addSubnode(self.expandMediaInputButton) } override func didLoad() { super.didLoad() - let gestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleLongPress(_:))) - gestureRecognizer.minimumPressDuration = 0.4 + let gestureRecognizer = ContextGesture(target: nil, action: nil) self.gestureRecognizer = gestureRecognizer - self.sendButton.addGestureRecognizer(gestureRecognizer) + self.sendButton.view.addGestureRecognizer(gestureRecognizer) + gestureRecognizer.activated = { [weak self] recognizer in + guard let strongSelf = self else { + return + } + if !strongSelf.sendButtonHasApplyIcon { + strongSelf.sendButtonLongPressed?(strongSelf.sendButton, recognizer) + } + } } @objc func handleLongPress(_ gestureRecognizer: UILongPressGestureRecognizer) { if !self.sendButtonHasApplyIcon && gestureRecognizer.state == .began { - self.sendButtonLongPressed?() + //self.sendButtonLongPressed?() } } diff --git a/submodules/TelegramUI/TelegramUI/OverlayPlayerControllerNode.swift b/submodules/TelegramUI/TelegramUI/OverlayPlayerControllerNode.swift index 0074f5a77d..3af972645b 100644 --- a/submodules/TelegramUI/TelegramUI/OverlayPlayerControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/OverlayPlayerControllerNode.swift @@ -146,7 +146,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu tagMask = .voiceOrInstantVideo } - self.historyNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: .message(initialMessageId), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: currentIsReversed)) + self.historyNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), tagMask: tagMask, subject: .message(initialMessageId), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), updatingMedia: .single([:]), mode: .list(search: false, reversed: currentIsReversed)) super.init() @@ -467,7 +467,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu tagMask = .voiceOrInstantVideo } - let historyNode = ChatHistoryListNode(context: self.context, chatLocation: .peer(self.peerId), tagMask: tagMask, subject: .message(messageId), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed)) + let historyNode = ChatHistoryListNode(context: self.context, chatLocation: .peer(self.peerId), tagMask: tagMask, subject: .message(messageId), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), updatingMedia: .single([:]), mode: .list(search: false, reversed: self.currentIsReversed)) historyNode.preloadPages = true historyNode.stackFromBottom = true historyNode.updateFloatingHeaderOffset = { [weak self] offset, _ in diff --git a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift index 653c05a846..4554dbd552 100644 --- a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift +++ b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift @@ -526,7 +526,7 @@ public class PeerMediaCollectionController: TelegramBaseController { }, openLinkEditing: { }, reportPeerIrrelevantGeoLocation: { }, displaySlowmodeTooltip: { _, _ in - }, displaySendMessageOptions: { + }, displaySendMessageOptions: { _, _ in }, openScheduledMessages: { }, displaySearchResultsTooltip: { _, _ in }, statuses: nil)