mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-15 18:59:54 +00:00
Improve send message actions
This commit is contained in:
parent
ae5eac1e52
commit
433d5c8ed9
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -112,7 +112,7 @@ final class ChatRecentActionsController: TelegramBaseController {
|
||||
}, openLinkEditing: {
|
||||
}, reportPeerIrrelevantGeoLocation: {
|
||||
}, displaySlowmodeTooltip: { _, _ in
|
||||
}, displaySendMessageOptions: {
|
||||
}, displaySendMessageOptions: { _, _ in
|
||||
}, openScheduledMessages: {
|
||||
}, displaySearchResultsTooltip: { _, _ in
|
||||
}, statuses: nil)
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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?()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -526,7 +526,7 @@ public class PeerMediaCollectionController: TelegramBaseController {
|
||||
}, openLinkEditing: {
|
||||
}, reportPeerIrrelevantGeoLocation: {
|
||||
}, displaySlowmodeTooltip: { _, _ in
|
||||
}, displaySendMessageOptions: {
|
||||
}, displaySendMessageOptions: { _, _ in
|
||||
}, openScheduledMessages: {
|
||||
}, displaySearchResultsTooltip: { _, _ in
|
||||
}, statuses: nil)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user