mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Various Fixes
This commit is contained in:
parent
273c34bc5c
commit
8f8aa37020
13 changed files with 373 additions and 305 deletions
|
|
@ -55,9 +55,15 @@ public final class PeerSelectionControllerParams {
|
|||
}
|
||||
}
|
||||
|
||||
public enum PeerSelectionControllerSendMode {
|
||||
case generic
|
||||
case silent
|
||||
case schedule
|
||||
}
|
||||
|
||||
public protocol PeerSelectionController: ViewController {
|
||||
var peerSelected: ((Peer) -> Void)? { get set }
|
||||
var multiplePeersSelected: (([Peer], NSAttributedString) -> Void)? { get set }
|
||||
var multiplePeersSelected: (([Peer], NSAttributedString, PeerSelectionControllerSendMode) -> Void)? { get set }
|
||||
var inProgress: Bool { get set }
|
||||
var customDismiss: (() -> Void)? { get set }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -901,32 +901,32 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
|||
}).start()
|
||||
|
||||
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled], multipleSelection: true))
|
||||
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, messageText in
|
||||
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, messageText, mode in
|
||||
guard let strongSelf = self, let strongController = peerSelectionController else {
|
||||
return
|
||||
}
|
||||
strongController.dismiss()
|
||||
|
||||
for peer in peers {
|
||||
var result: [EnqueueMessage] = []
|
||||
if messageText.string.count > 0 {
|
||||
let inputText = convertMarkdownToAttributes(messageText)
|
||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||
if text.length != 0 {
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
var result: [EnqueueMessage] = []
|
||||
if messageText.string.count > 0 {
|
||||
let inputText = convertMarkdownToAttributes(messageText)
|
||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||
if text.length != 0 {
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
}
|
||||
|
||||
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
|
||||
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
|
||||
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil)
|
||||
})
|
||||
|
||||
for peer in peers {
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result)
|
||||
|> deliverOnMainQueue).start(next: { messageIds in
|
||||
if let strongSelf = self {
|
||||
|
|
|
|||
|
|
@ -957,7 +957,7 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi
|
|||
|
||||
contentParentNode.willUpdateIsExtractedToContextPreview?(false, .animated(duration: 0.2, curve: .easeInOut))
|
||||
} else {
|
||||
if let snapshotView = contentParentNode.contentNode.view.snapshotContentTree() {
|
||||
if let snapshotView = contentParentNode.contentNode.view.snapshotContentTree(keepTransform: true) {
|
||||
self.contentContainerNode.view.addSubview(snapshotView)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2438,27 +2438,21 @@ static CGPoint TGCameraControllerClampPointToScreenSize(__unused id self, __unus
|
|||
PGCameraMode newMode = PGCameraModeUndefined;
|
||||
if (gestureRecognizer == _photoSwipeGestureRecognizer)
|
||||
{
|
||||
if (_camera.cameraMode == PGCameraModePhoto && _intent == TGCameraControllerGenericIntent)
|
||||
newMode = PGCameraModePhotoScan;
|
||||
else if (_camera.cameraMode != PGCameraModePhotoScan)
|
||||
newMode = PGCameraModePhoto;
|
||||
newMode = PGCameraModePhoto;
|
||||
}
|
||||
else if (gestureRecognizer == _videoSwipeGestureRecognizer)
|
||||
{
|
||||
if (_camera.cameraMode == PGCameraModePhotoScan) {
|
||||
if (_items.count == 0)
|
||||
newMode = PGCameraModePhoto;
|
||||
if (_intent == TGCameraControllerAvatarIntent) {
|
||||
newMode = PGCameraModeSquareVideo;
|
||||
} else {
|
||||
if (_intent == TGCameraControllerAvatarIntent) {
|
||||
newMode = PGCameraModeSquareVideo;
|
||||
} else {
|
||||
newMode = PGCameraModeVideo;
|
||||
}
|
||||
newMode = PGCameraModeVideo;
|
||||
}
|
||||
}
|
||||
|
||||
if (newMode != PGCameraModeUndefined && _camera.cameraMode != newMode) {
|
||||
[self _updateCameraMode:newMode updateInterface:true];
|
||||
if (newMode != PGCameraModeUndefined && _camera.cameraMode != newMode)
|
||||
{
|
||||
[_camera setCameraMode:newMode];
|
||||
[_interfaceView setCameraMode:newMode];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -245,19 +245,6 @@
|
|||
|
||||
if (_selectionContext.allowGrouping)
|
||||
{
|
||||
/*_groupButton = [[TGMediaPickerGroupButton alloc] initWithFrame:CGRectMake(0, 0, 38.0f, 38.0f)];
|
||||
[_groupButton setHidden:true animated:false];
|
||||
_groupButton.selected = _selectionContext.grouping;
|
||||
[_groupButton addTarget:self action:@selector(toggleGrouping) forControlEvents:UIControlEventTouchUpInside];
|
||||
[_wrapperView addSubview:_groupButton];
|
||||
|
||||
_groupingChangedDisposable = [[_selectionContext groupingChangedSignal] startWithNext:^(NSNumber *next)
|
||||
{
|
||||
__strong TGMediaPickerGalleryInterfaceView *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
[strongSelf->_groupButton setSelected:next.boolValue];
|
||||
}];*/
|
||||
|
||||
if (_editingContext != nil)
|
||||
{
|
||||
_timersChangedDisposable = [_editingContext.timersUpdatedSignal startWithNext:^(__unused NSNumber *next)
|
||||
|
|
|
|||
|
|
@ -6603,10 +6603,18 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
|
||||
let _ = ApplicationSpecificNotice.incrementChatMessageOptionsTip(accountManager: strongSelf.context.sharedContext.accountManager, count: 4).start()
|
||||
|
||||
let controller = ChatSendMessageActionSheetController(context: strongSelf.context, controllerInteraction: strongSelf.controllerInteraction, interfaceState: strongSelf.presentationInterfaceState, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, completion: { [weak self] in
|
||||
let controller = ChatSendMessageActionSheetController(context: strongSelf.context, interfaceState: strongSelf.presentationInterfaceState, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, completion: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.supportedOrientations = previousSupportedOrientations
|
||||
}
|
||||
}, sendMessage: { [weak self] silently in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerInteraction?.sendCurrentMessage(silently)
|
||||
}
|
||||
}, schedule: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.controllerInteraction?.scheduleCurrentMessage()
|
||||
}
|
||||
})
|
||||
strongSelf.sendMessageActionsController = controller
|
||||
if layout.isNonExclusive {
|
||||
|
|
@ -10917,80 +10925,97 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
controller.present(textAlertController(context: context, title: nil, text: presentationData.strings.Forward_ErrorDisabledForChat, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), in: .window(.root))
|
||||
}
|
||||
controller.multiplePeersSelected = { [weak self, weak controller] peers, messageText in
|
||||
controller.multiplePeersSelected = { [weak self, weak controller] peers, messageText, mode in
|
||||
guard let strongSelf = self, let strongController = controller else {
|
||||
return
|
||||
}
|
||||
strongController.dismiss()
|
||||
|
||||
for peer in peers {
|
||||
var result: [EnqueueMessage] = []
|
||||
if messageText.string.count > 0 {
|
||||
let inputText = convertMarkdownToAttributes(messageText)
|
||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||
if text.length != 0 {
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
var result: [EnqueueMessage] = []
|
||||
if messageText.string.count > 0 {
|
||||
let inputText = convertMarkdownToAttributes(messageText)
|
||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||
if text.length != 0 {
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
}
|
||||
|
||||
result.append(contentsOf: messages.map { message -> EnqueueMessage in
|
||||
return .forward(source: message.id, grouping: .auto, attributes: [], correlationId: nil)
|
||||
})
|
||||
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result)
|
||||
|> deliverOnMainQueue).start(next: { messageIds in
|
||||
if let strongSelf = self {
|
||||
let signals: [Signal<Bool, NoError>] = messageIds.compactMap({ id -> Signal<Bool, NoError>? in
|
||||
guard let id = id else {
|
||||
return nil
|
||||
}
|
||||
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|
||||
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
|
||||
if status != nil {
|
||||
return .never()
|
||||
} else {
|
||||
return .single(true)
|
||||
}
|
||||
|
||||
result.append(contentsOf: messages.map { message -> EnqueueMessage in
|
||||
return .forward(source: message.id, grouping: .auto, attributes: [], correlationId: nil)
|
||||
})
|
||||
|
||||
let commit: ([EnqueueMessage]) -> Void = { result in
|
||||
for peer in peers {
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result)
|
||||
|> deliverOnMainQueue).start(next: { messageIds in
|
||||
if let strongSelf = self {
|
||||
let signals: [Signal<Bool, NoError>] = messageIds.compactMap({ id -> Signal<Bool, NoError>? in
|
||||
guard let id = id else {
|
||||
return nil
|
||||
}
|
||||
return strongSelf.context.account.pendingMessageManager.pendingMessageStatus(id)
|
||||
|> mapToSignal { status, _ -> Signal<Bool, NoError> in
|
||||
if status != nil {
|
||||
return .never()
|
||||
} else {
|
||||
return .single(true)
|
||||
}
|
||||
}
|
||||
|> take(1)
|
||||
})
|
||||
if strongSelf.shareStatusDisposable == nil {
|
||||
strongSelf.shareStatusDisposable = MetaDisposable()
|
||||
}
|
||||
|> take(1)
|
||||
})
|
||||
if strongSelf.shareStatusDisposable == nil {
|
||||
strongSelf.shareStatusDisposable = MetaDisposable()
|
||||
strongSelf.shareStatusDisposable?.set((combineLatest(signals)
|
||||
|> deliverOnMainQueue).start())
|
||||
}
|
||||
strongSelf.shareStatusDisposable?.set((combineLatest(signals)
|
||||
|> deliverOnMainQueue).start())
|
||||
}
|
||||
})
|
||||
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text: String
|
||||
var savedMessages = false
|
||||
if peers.count == 1, let peerId = peers.first?.id, peerId == strongSelf.context.account.peerId {
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many
|
||||
savedMessages = true
|
||||
} else {
|
||||
if peers.count == 1, let peer = peers.first {
|
||||
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).string
|
||||
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
|
||||
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).string
|
||||
} else if let peer = peers.first {
|
||||
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").string
|
||||
})
|
||||
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
let text: String
|
||||
var savedMessages = false
|
||||
if peers.count == 1, let peerId = peers.first?.id, peerId == strongSelf.context.account.peerId {
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_SavedMessages_One : presentationData.strings.Conversation_ForwardTooltip_SavedMessages_Many
|
||||
savedMessages = true
|
||||
} else {
|
||||
text = ""
|
||||
if peers.count == 1, let peer = peers.first {
|
||||
let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_Chat_One(peerName).string : presentationData.strings.Conversation_ForwardTooltip_Chat_Many(peerName).string
|
||||
} else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last {
|
||||
let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string : presentationData.strings.Conversation_ForwardTooltip_TwoChats_Many(firstPeerName, secondPeerName).string
|
||||
} else if let peer = peers.first {
|
||||
let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)
|
||||
text = messages.count == 1 ? presentationData.strings.Conversation_ForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string : presentationData.strings.Conversation_ForwardTooltip_ManyChats_Many(peerName, "\(peers.count - 1)").string
|
||||
} else {
|
||||
text = ""
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
|
||||
}
|
||||
|
||||
strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { _ in return false }), in: .current)
|
||||
}
|
||||
|
||||
switch mode {
|
||||
case .generic:
|
||||
commit(result)
|
||||
case .silent:
|
||||
let transformedMessages = strongSelf.transformEnqueueMessages(result, silentPosting: true)
|
||||
commit(transformedMessages)
|
||||
case .schedule:
|
||||
strongSelf.presentScheduleTimePicker(completion: { [weak self] scheduleTime in
|
||||
if let strongSelf = self {
|
||||
let transformedMessages = strongSelf.transformEnqueueMessages(result, silentPosting: false, scheduleTime: scheduleTime)
|
||||
commit(transformedMessages)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
controller.peerSelected = { [weak self, weak controller] peer in
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
private var appliedHasAvatar = false
|
||||
private var appliedCurrentlyPlaying = false
|
||||
private var appliedAutomaticDownload = false
|
||||
private var avatarOffset: CGFloat?
|
||||
|
||||
private var animatingHeight: Bool {
|
||||
return self.apparentHeightTransition != nil
|
||||
|
|
@ -78,7 +79,14 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
super.init(layerBacked: false)
|
||||
|
||||
self.interactiveVideoNode.shouldOpen = { [weak self] in
|
||||
return !(self?.animatingHeight ?? false)
|
||||
if let strongSelf = self {
|
||||
if let item = strongSelf.item, item.message.id.namespace == Namespaces.Message.Local {
|
||||
return false
|
||||
}
|
||||
return !strongSelf.animatingHeight
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
self.containerNode.shouldBegin = { [weak self] location in
|
||||
|
|
@ -337,7 +345,8 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
}
|
||||
|
||||
var isPlaying = false
|
||||
var displaySize = layoutConstants.instantVideo.dimensions
|
||||
let normalDisplaySize = layoutConstants.instantVideo.dimensions
|
||||
var displaySize = normalDisplaySize
|
||||
let maximumDisplaySize = CGSize(width: min(404, params.width - 20.0), height: min(404, params.width - 20.0))
|
||||
var effectiveAvatarInset = avatarInset
|
||||
if item.associatedData.currentlyPlayingMessageId == item.message.index {
|
||||
|
|
@ -499,7 +508,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
forwardBackgroundImage = graphics.chatServiceBubbleFillImage
|
||||
}
|
||||
|
||||
var maxContentWidth = videoLayout.contentSize.width
|
||||
var maxContentWidth = normalDisplaySize.width
|
||||
var actionButtonsFinalize: ((CGFloat) -> (CGSize, (_ animated: Bool) -> ChatMessageActionButtonsNode))?
|
||||
if let replyMarkup = replyMarkup {
|
||||
let (minWidth, buttonsLayout) = actionButtonsLayout(item.context, item.presentationData.theme, item.presentationData.chatBubbleCorners, item.presentationData.strings, replyMarkup, item.message, maxContentWidth)
|
||||
|
|
@ -536,6 +545,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
strongSelf.appliedHasAvatar = hasAvatar
|
||||
strongSelf.appliedForwardInfo = (forwardSource, forwardAuthorSignature)
|
||||
strongSelf.appliedCurrentlyPlaying = isPlaying
|
||||
strongSelf.appliedAutomaticDownload = automaticDownload
|
||||
|
||||
strongSelf.updateAccessibilityData(accessibilityData)
|
||||
|
||||
|
|
@ -552,171 +562,183 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
videoApply(videoLayoutData, transition)
|
||||
}
|
||||
|
||||
if currentPlaying != isPlaying {
|
||||
if isPlaying {
|
||||
strongSelf.avatarOffset = -100.0
|
||||
} else {
|
||||
strongSelf.avatarOffset = nil
|
||||
}
|
||||
strongSelf.updateSelectionState(animated: true)
|
||||
strongSelf.updateAttachedAvatarNodeOffset(offset: strongSelf.avatarOffset ?? 0.0, transition: .animated(duration: 0.3, curve: .easeInOut))
|
||||
}
|
||||
|
||||
strongSelf.interactiveVideoNode.view.disablesInteractiveTransitionGestureRecognizer = isPlaying
|
||||
|
||||
strongSelf.contextSourceNode.contentRect = videoFrame
|
||||
strongSelf.containerNode.targetNodeForActivationProgressContentRect = strongSelf.contextSourceNode.contentRect
|
||||
|
||||
if let updatedShareButtonNode = updatedShareButtonNode {
|
||||
if updatedShareButtonNode !== strongSelf.shareButtonNode {
|
||||
if let shareButtonNode = strongSelf.shareButtonNode {
|
||||
shareButtonNode.removeFromSupernode()
|
||||
}
|
||||
strongSelf.shareButtonNode = updatedShareButtonNode
|
||||
strongSelf.addSubnode(updatedShareButtonNode)
|
||||
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||
updatedShareButtonNode.frame = CGRect(origin: CGPoint(x: videoFrame.maxX - 7.0, y: videoFrame.maxY - 24.0 - buttonSize.height), size: buttonSize)
|
||||
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
||||
shareButtonNode.removeFromSupernode()
|
||||
strongSelf.shareButtonNode = nil
|
||||
}
|
||||
|
||||
if let updatedReplyBackgroundNode = updatedReplyBackgroundNode {
|
||||
if strongSelf.replyBackgroundNode == nil {
|
||||
strongSelf.replyBackgroundNode = updatedReplyBackgroundNode
|
||||
strongSelf.addSubnode(updatedReplyBackgroundNode)
|
||||
updatedReplyBackgroundNode.image = replyBackgroundImage
|
||||
} else {
|
||||
strongSelf.replyBackgroundNode?.image = replyBackgroundImage
|
||||
}
|
||||
} else if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
||||
replyBackgroundNode.removeFromSupernode()
|
||||
strongSelf.replyBackgroundNode = nil
|
||||
}
|
||||
|
||||
if let (viaBotLayout, viaBotApply) = viaBotApply {
|
||||
let viaBotNode = viaBotApply()
|
||||
if strongSelf.viaBotNode == nil {
|
||||
strongSelf.viaBotNode = viaBotNode
|
||||
strongSelf.addSubnode(viaBotNode)
|
||||
}
|
||||
let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - viaBotLayout.size.width - layoutConstants.bubble.edgeInset - 10.0)), y: 8.0), size: viaBotLayout.size)
|
||||
viaBotNode.frame = viaBotFrame
|
||||
strongSelf.replyBackgroundNode?.frame = CGRect(origin: CGPoint(x: viaBotFrame.minX - 4.0, y: viaBotFrame.minY - 2.0), size: CGSize(width: viaBotFrame.size.width + 8.0, height: viaBotFrame.size.height + 5.0))
|
||||
} else if let viaBotNode = strongSelf.viaBotNode {
|
||||
viaBotNode.removeFromSupernode()
|
||||
strongSelf.viaBotNode = nil
|
||||
}
|
||||
|
||||
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
||||
let replyInfoNode = replyInfoApply()
|
||||
if strongSelf.replyInfoNode == nil {
|
||||
strongSelf.replyInfoNode = replyInfoNode
|
||||
strongSelf.addSubnode(replyInfoNode)
|
||||
}
|
||||
var viaBotSize = CGSize()
|
||||
if let viaBotNode = strongSelf.viaBotNode {
|
||||
viaBotSize = viaBotNode.frame.size
|
||||
}
|
||||
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - max(replyInfoSize.width, viaBotSize.width) - layoutConstants.bubble.edgeInset - 10.0)), y: 8.0 + viaBotSize.height), size: replyInfoSize)
|
||||
if let viaBotNode = strongSelf.viaBotNode {
|
||||
if replyInfoFrame.minX < viaBotNode.frame.minX {
|
||||
viaBotNode.frame = viaBotNode.frame.offsetBy(dx: replyInfoFrame.minX - viaBotNode.frame.minX, dy: 0.0)
|
||||
}
|
||||
}
|
||||
replyInfoNode.frame = replyInfoFrame
|
||||
strongSelf.replyBackgroundNode?.frame = CGRect(origin: CGPoint(x: replyInfoFrame.minX - 4.0, y: replyInfoFrame.minY - viaBotSize.height - 2.0), size: CGSize(width: max(replyInfoFrame.size.width, viaBotSize.width) + 8.0, height: replyInfoFrame.size.height + viaBotSize.height + 5.0))
|
||||
} else if let replyInfoNode = strongSelf.replyInfoNode {
|
||||
replyInfoNode.removeFromSupernode()
|
||||
strongSelf.replyInfoNode = nil
|
||||
}
|
||||
|
||||
if isFailed {
|
||||
let deliveryFailedNode: ChatMessageDeliveryFailedNode
|
||||
var isAppearing = false
|
||||
if let current = strongSelf.deliveryFailedNode {
|
||||
deliveryFailedNode = current
|
||||
} else {
|
||||
isAppearing = true
|
||||
deliveryFailedNode = ChatMessageDeliveryFailedNode(tapped: {
|
||||
if let item = self?.item {
|
||||
item.controllerInteraction.requestRedeliveryOfFailedMessages(item.content.firstMessage.id)
|
||||
if !animating {
|
||||
if let updatedShareButtonNode = updatedShareButtonNode {
|
||||
if updatedShareButtonNode !== strongSelf.shareButtonNode {
|
||||
if let shareButtonNode = strongSelf.shareButtonNode {
|
||||
shareButtonNode.removeFromSupernode()
|
||||
}
|
||||
strongSelf.shareButtonNode = updatedShareButtonNode
|
||||
strongSelf.addSubnode(updatedShareButtonNode)
|
||||
updatedShareButtonNode.addTarget(strongSelf, action: #selector(strongSelf.shareButtonPressed), forControlEvents: .touchUpInside)
|
||||
}
|
||||
let buttonSize = updatedShareButtonNode.update(presentationData: item.presentationData, chatLocation: item.chatLocation, subject: item.associatedData.subject, message: item.message, account: item.context.account)
|
||||
updatedShareButtonNode.frame = CGRect(origin: CGPoint(x: min(params.width - buttonSize.width - 8.0, videoFrame.maxX - 7.0), y: videoFrame.maxY - 24.0 - buttonSize.height), size: buttonSize)
|
||||
} else if let shareButtonNode = strongSelf.shareButtonNode {
|
||||
shareButtonNode.removeFromSupernode()
|
||||
strongSelf.shareButtonNode = nil
|
||||
}
|
||||
|
||||
if let updatedReplyBackgroundNode = updatedReplyBackgroundNode {
|
||||
if strongSelf.replyBackgroundNode == nil {
|
||||
strongSelf.replyBackgroundNode = updatedReplyBackgroundNode
|
||||
strongSelf.addSubnode(updatedReplyBackgroundNode)
|
||||
updatedReplyBackgroundNode.image = replyBackgroundImage
|
||||
} else {
|
||||
strongSelf.replyBackgroundNode?.image = replyBackgroundImage
|
||||
}
|
||||
} else if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
||||
replyBackgroundNode.removeFromSupernode()
|
||||
strongSelf.replyBackgroundNode = nil
|
||||
}
|
||||
|
||||
if let (viaBotLayout, viaBotApply) = viaBotApply {
|
||||
let viaBotNode = viaBotApply()
|
||||
if strongSelf.viaBotNode == nil {
|
||||
strongSelf.viaBotNode = viaBotNode
|
||||
strongSelf.addSubnode(viaBotNode)
|
||||
}
|
||||
let viaBotFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - viaBotLayout.size.width - layoutConstants.bubble.edgeInset - 10.0)), y: 8.0), size: viaBotLayout.size)
|
||||
viaBotNode.frame = viaBotFrame
|
||||
strongSelf.replyBackgroundNode?.frame = CGRect(origin: CGPoint(x: viaBotFrame.minX - 4.0, y: viaBotFrame.minY - 2.0), size: CGSize(width: viaBotFrame.size.width + 8.0, height: viaBotFrame.size.height + 5.0))
|
||||
} else if let viaBotNode = strongSelf.viaBotNode {
|
||||
viaBotNode.removeFromSupernode()
|
||||
strongSelf.viaBotNode = nil
|
||||
}
|
||||
|
||||
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
||||
let replyInfoNode = replyInfoApply()
|
||||
if strongSelf.replyInfoNode == nil {
|
||||
strongSelf.replyInfoNode = replyInfoNode
|
||||
strongSelf.addSubnode(replyInfoNode)
|
||||
}
|
||||
var viaBotSize = CGSize()
|
||||
if let viaBotNode = strongSelf.viaBotNode {
|
||||
viaBotSize = viaBotNode.frame.size
|
||||
}
|
||||
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - max(replyInfoSize.width, viaBotSize.width) - layoutConstants.bubble.edgeInset - 10.0)), y: 8.0 + viaBotSize.height), size: replyInfoSize)
|
||||
if let viaBotNode = strongSelf.viaBotNode {
|
||||
if replyInfoFrame.minX < viaBotNode.frame.minX {
|
||||
viaBotNode.frame = viaBotNode.frame.offsetBy(dx: replyInfoFrame.minX - viaBotNode.frame.minX, dy: 0.0)
|
||||
}
|
||||
}
|
||||
replyInfoNode.frame = replyInfoFrame
|
||||
strongSelf.replyBackgroundNode?.frame = CGRect(origin: CGPoint(x: replyInfoFrame.minX - 4.0, y: replyInfoFrame.minY - viaBotSize.height - 2.0), size: CGSize(width: max(replyInfoFrame.size.width, viaBotSize.width) + 8.0, height: replyInfoFrame.size.height + viaBotSize.height + 5.0))
|
||||
} else if let replyInfoNode = strongSelf.replyInfoNode {
|
||||
replyInfoNode.removeFromSupernode()
|
||||
strongSelf.replyInfoNode = nil
|
||||
}
|
||||
|
||||
if isFailed {
|
||||
let deliveryFailedNode: ChatMessageDeliveryFailedNode
|
||||
var isAppearing = false
|
||||
if let current = strongSelf.deliveryFailedNode {
|
||||
deliveryFailedNode = current
|
||||
} else {
|
||||
isAppearing = true
|
||||
deliveryFailedNode = ChatMessageDeliveryFailedNode(tapped: {
|
||||
if let item = self?.item {
|
||||
item.controllerInteraction.requestRedeliveryOfFailedMessages(item.content.firstMessage.id)
|
||||
}
|
||||
})
|
||||
strongSelf.deliveryFailedNode = deliveryFailedNode
|
||||
strongSelf.addSubnode(deliveryFailedNode)
|
||||
}
|
||||
let deliveryFailedSize = deliveryFailedNode.updateLayout(theme: item.presentationData.theme.theme)
|
||||
let deliveryFailedFrame = CGRect(origin: CGPoint(x: videoFrame.maxX + deliveryFailedInset - deliveryFailedSize.width, y: videoFrame.maxY - deliveryFailedSize.height), size: deliveryFailedSize)
|
||||
if isAppearing {
|
||||
deliveryFailedNode.frame = deliveryFailedFrame
|
||||
transition.animatePositionAdditive(node: deliveryFailedNode, offset: CGPoint(x: deliveryFailedInset, y: 0.0))
|
||||
} else {
|
||||
transition.updateFrame(node: deliveryFailedNode, frame: deliveryFailedFrame)
|
||||
}
|
||||
} else if let deliveryFailedNode = strongSelf.deliveryFailedNode {
|
||||
strongSelf.deliveryFailedNode = nil
|
||||
transition.updateAlpha(node: deliveryFailedNode, alpha: 0.0)
|
||||
transition.updateFrame(node: deliveryFailedNode, frame: deliveryFailedNode.frame.offsetBy(dx: 24.0, dy: 0.0), completion: { [weak deliveryFailedNode] _ in
|
||||
deliveryFailedNode?.removeFromSupernode()
|
||||
})
|
||||
strongSelf.deliveryFailedNode = deliveryFailedNode
|
||||
strongSelf.addSubnode(deliveryFailedNode)
|
||||
}
|
||||
let deliveryFailedSize = deliveryFailedNode.updateLayout(theme: item.presentationData.theme.theme)
|
||||
let deliveryFailedFrame = CGRect(origin: CGPoint(x: videoFrame.maxX + deliveryFailedInset - deliveryFailedSize.width, y: videoFrame.maxY - deliveryFailedSize.height), size: deliveryFailedSize)
|
||||
if isAppearing {
|
||||
deliveryFailedNode.frame = deliveryFailedFrame
|
||||
transition.animatePositionAdditive(node: deliveryFailedNode, offset: CGPoint(x: deliveryFailedInset, y: 0.0))
|
||||
} else {
|
||||
transition.updateFrame(node: deliveryFailedNode, frame: deliveryFailedFrame)
|
||||
}
|
||||
} else if let deliveryFailedNode = strongSelf.deliveryFailedNode {
|
||||
strongSelf.deliveryFailedNode = nil
|
||||
transition.updateAlpha(node: deliveryFailedNode, alpha: 0.0)
|
||||
transition.updateFrame(node: deliveryFailedNode, frame: deliveryFailedNode.frame.offsetBy(dx: 24.0, dy: 0.0), completion: { [weak deliveryFailedNode] _ in
|
||||
deliveryFailedNode?.removeFromSupernode()
|
||||
})
|
||||
}
|
||||
|
||||
if let updatedForwardBackgroundNode = updatedForwardBackgroundNode {
|
||||
if strongSelf.forwardBackgroundNode == nil {
|
||||
strongSelf.forwardBackgroundNode = updatedForwardBackgroundNode
|
||||
strongSelf.addSubnode(updatedForwardBackgroundNode)
|
||||
updatedForwardBackgroundNode.image = forwardBackgroundImage
|
||||
}
|
||||
} else if let forwardBackgroundNode = strongSelf.forwardBackgroundNode {
|
||||
forwardBackgroundNode.removeFromSupernode()
|
||||
strongSelf.forwardBackgroundNode = nil
|
||||
}
|
||||
|
||||
if let (forwardInfoSize, forwardInfoApply) = forwardInfoSizeApply {
|
||||
let forwardInfoNode = forwardInfoApply(forwardInfoSize.width)
|
||||
if strongSelf.forwardInfoNode == nil {
|
||||
strongSelf.forwardInfoNode = forwardInfoNode
|
||||
strongSelf.addSubnode(forwardInfoNode)
|
||||
forwardInfoNode.openPsa = { [weak strongSelf] type, sourceNode in
|
||||
guard let strongSelf = strongSelf, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
item.controllerInteraction.displayPsa(type, sourceNode)
|
||||
|
||||
if let updatedForwardBackgroundNode = updatedForwardBackgroundNode {
|
||||
if strongSelf.forwardBackgroundNode == nil {
|
||||
strongSelf.forwardBackgroundNode = updatedForwardBackgroundNode
|
||||
strongSelf.addSubnode(updatedForwardBackgroundNode)
|
||||
updatedForwardBackgroundNode.image = forwardBackgroundImage
|
||||
}
|
||||
} else if let forwardBackgroundNode = strongSelf.forwardBackgroundNode {
|
||||
forwardBackgroundNode.removeFromSupernode()
|
||||
strongSelf.forwardBackgroundNode = nil
|
||||
}
|
||||
let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0) : (params.width - params.rightInset - forwardInfoSize.width - layoutConstants.bubble.edgeInset - 12.0)), y: 8.0), size: forwardInfoSize)
|
||||
forwardInfoNode.frame = forwardInfoFrame
|
||||
strongSelf.forwardBackgroundNode?.frame = CGRect(origin: CGPoint(x: forwardInfoFrame.minX - 6.0, y: forwardInfoFrame.minY - 2.0), size: CGSize(width: forwardInfoFrame.size.width + 10.0, height: forwardInfoFrame.size.height + 4.0))
|
||||
} else if let forwardInfoNode = strongSelf.forwardInfoNode {
|
||||
forwardInfoNode.removeFromSupernode()
|
||||
strongSelf.forwardInfoNode = nil
|
||||
}
|
||||
|
||||
if let actionButtonsSizeAndApply = actionButtonsSizeAndApply {
|
||||
var animated = false
|
||||
if let _ = strongSelf.actionButtonsNode {
|
||||
if case .System = animation {
|
||||
animated = true
|
||||
}
|
||||
}
|
||||
let actionButtonsNode = actionButtonsSizeAndApply.1(animated)
|
||||
let previousFrame = actionButtonsNode.frame
|
||||
let actionButtonsFrame = CGRect(origin: CGPoint(x: videoFrame.minX, y: videoFrame.maxY), size: actionButtonsSizeAndApply.0)
|
||||
actionButtonsNode.frame = actionButtonsFrame
|
||||
if actionButtonsNode !== strongSelf.actionButtonsNode {
|
||||
strongSelf.actionButtonsNode = actionButtonsNode
|
||||
actionButtonsNode.buttonPressed = { button in
|
||||
if let strongSelf = self {
|
||||
strongSelf.performMessageButtonAction(button: button)
|
||||
|
||||
if let (forwardInfoSize, forwardInfoApply) = forwardInfoSizeApply {
|
||||
let forwardInfoNode = forwardInfoApply(forwardInfoSize.width)
|
||||
if strongSelf.forwardInfoNode == nil {
|
||||
strongSelf.forwardInfoNode = forwardInfoNode
|
||||
strongSelf.addSubnode(forwardInfoNode)
|
||||
forwardInfoNode.openPsa = { [weak strongSelf] type, sourceNode in
|
||||
guard let strongSelf = strongSelf, let item = strongSelf.item else {
|
||||
return
|
||||
}
|
||||
item.controllerInteraction.displayPsa(type, sourceNode)
|
||||
}
|
||||
}
|
||||
actionButtonsNode.buttonLongTapped = { button in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentMessageButtonContextMenu(button: button)
|
||||
let forwardInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 12.0) : (params.width - params.rightInset - forwardInfoSize.width - layoutConstants.bubble.edgeInset - 12.0)), y: 8.0), size: forwardInfoSize)
|
||||
forwardInfoNode.frame = forwardInfoFrame
|
||||
strongSelf.forwardBackgroundNode?.frame = CGRect(origin: CGPoint(x: forwardInfoFrame.minX - 6.0, y: forwardInfoFrame.minY - 2.0), size: CGSize(width: forwardInfoFrame.size.width + 10.0, height: forwardInfoFrame.size.height + 4.0))
|
||||
} else if let forwardInfoNode = strongSelf.forwardInfoNode {
|
||||
forwardInfoNode.removeFromSupernode()
|
||||
strongSelf.forwardInfoNode = nil
|
||||
}
|
||||
|
||||
if let actionButtonsSizeAndApply = actionButtonsSizeAndApply {
|
||||
var animated = false
|
||||
if let _ = strongSelf.actionButtonsNode {
|
||||
if case .System = animation {
|
||||
animated = true
|
||||
}
|
||||
}
|
||||
strongSelf.addSubnode(actionButtonsNode)
|
||||
} else {
|
||||
if case let .System(duration) = animation {
|
||||
actionButtonsNode.layer.animateFrame(from: previousFrame, to: actionButtonsFrame, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
let actionButtonsNode = actionButtonsSizeAndApply.1(animated)
|
||||
let previousFrame = actionButtonsNode.frame
|
||||
let actionButtonsFrame = CGRect(origin: CGPoint(x: videoFrame.minX, y: videoFrame.maxY), size: actionButtonsSizeAndApply.0)
|
||||
actionButtonsNode.frame = actionButtonsFrame
|
||||
if actionButtonsNode !== strongSelf.actionButtonsNode {
|
||||
strongSelf.actionButtonsNode = actionButtonsNode
|
||||
actionButtonsNode.buttonPressed = { button in
|
||||
if let strongSelf = self {
|
||||
strongSelf.performMessageButtonAction(button: button)
|
||||
}
|
||||
}
|
||||
actionButtonsNode.buttonLongTapped = { button in
|
||||
if let strongSelf = self {
|
||||
strongSelf.presentMessageButtonContextMenu(button: button)
|
||||
}
|
||||
}
|
||||
strongSelf.addSubnode(actionButtonsNode)
|
||||
} else {
|
||||
if case let .System(duration) = animation {
|
||||
actionButtonsNode.layer.animateFrame(from: previousFrame, to: actionButtonsFrame, duration: duration, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
}
|
||||
}
|
||||
} else if let actionButtonsNode = strongSelf.actionButtonsNode {
|
||||
actionButtonsNode.removeFromSupernode()
|
||||
strongSelf.actionButtonsNode = nil
|
||||
}
|
||||
} else if let actionButtonsNode = strongSelf.actionButtonsNode {
|
||||
actionButtonsNode.removeFromSupernode()
|
||||
strongSelf.actionButtonsNode = nil
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -895,7 +917,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
bounds.origin.x = -translation.x
|
||||
self.bounds = bounds
|
||||
|
||||
self.updateAttachedAvatarNodeOffset(offset: translation.x, transition: .immediate)
|
||||
self.updateAttachedAvatarNodeOffset(offset: self.avatarOffset ?? translation.x, transition: .immediate)
|
||||
|
||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||
swipeToReplyNode.frame = CGRect(origin: CGPoint(x: bounds.size.width, y: floor((self.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0))
|
||||
|
|
@ -932,7 +954,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
self.bounds = bounds
|
||||
self.layer.animateBounds(from: previousBounds, to: bounds, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
|
||||
self.updateAttachedAvatarNodeOffset(offset: 0.0, transition: .animated(duration: 0.3, curve: .spring))
|
||||
self.updateAttachedAvatarNodeOffset(offset: self.avatarOffset ?? 0.0, transition: .animated(duration: 0.3, curve: .spring))
|
||||
|
||||
if let swipeToReplyNode = self.swipeToReplyNode {
|
||||
self.swipeToReplyNode = nil
|
||||
|
|
@ -972,7 +994,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
selected = selectionState.selectedIds.contains(item.message.id)
|
||||
incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||
|
||||
let offset: CGFloat = incoming ? 42.0 : 0.0
|
||||
let offset: CGFloat = incoming || self.appliedCurrentlyPlaying ? 42.0 : 0.0
|
||||
|
||||
if let selectionNode = self.selectionNode {
|
||||
let selectionFrame = CGRect(origin: CGPoint(x: -offset, y: 0.0), size: CGSize(width: self.contentBounds.size.width, height: self.contentBounds.size.height))
|
||||
|
|
@ -1067,7 +1089,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
override func animateFrameTransition(_ progress: CGFloat, _ currentValue: CGFloat) {
|
||||
super.animateFrameTransition(progress, currentValue)
|
||||
|
||||
guard let item = self.appliedItem, let params = self.appliedParams, progress > 0.0, let (initialHeight, targetHeight) = self.apparentHeightTransition else {
|
||||
guard let item = self.appliedItem, let params = self.appliedParams, progress > 0.0, let (initialHeight, targetHeight) = self.apparentHeightTransition, !targetHeight.isZero && !initialHeight.isZero else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -1140,7 +1162,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
|
||||
if let shareButtonNode = self.shareButtonNode {
|
||||
let buttonSize = shareButtonNode.frame.size
|
||||
shareButtonNode.frame = CGRect(origin: CGPoint(x: videoFrame.maxX - 7.0, y: videoFrame.maxY - 24.0 - buttonSize.height), size: buttonSize)
|
||||
shareButtonNode.frame = CGRect(origin: CGPoint(x: min(params.width - buttonSize.width - 8.0, videoFrame.maxX - 7.0), y: videoFrame.maxY - 24.0 - buttonSize.height), size: buttonSize)
|
||||
}
|
||||
|
||||
if let viaBotNode = self.viaBotNode {
|
||||
|
|
@ -1178,5 +1200,11 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||
forwardInfoNode.frame = forwardInfoFrame
|
||||
self.forwardBackgroundNode?.frame = CGRect(origin: CGPoint(x: forwardInfoFrame.minX - 6.0, y: forwardInfoFrame.minY - 2.0), size: CGSize(width: forwardInfoFrame.size.width + 10.0, height: forwardInfoFrame.size.height + 4.0))
|
||||
}
|
||||
|
||||
if let actionButtonsNode = self.actionButtonsNode {
|
||||
let actionButtonsSize = actionButtonsNode.frame.size
|
||||
let actionButtonsFrame = CGRect(origin: CGPoint(x: videoFrame.minX, y: videoFrame.maxY), size: actionButtonsSize)
|
||||
actionButtonsNode.frame = actionButtonsFrame
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -707,9 +707,6 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||
if let playbackStatusNode = self.playbackStatusNode {
|
||||
self.playbackStatusNode = nil
|
||||
playbackStatusNode.removeFromSupernode()
|
||||
// playbackStatusNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak playbackStatusNode] _ in
|
||||
// playbackStatusNode?.removeFromSupernode()
|
||||
// })
|
||||
}
|
||||
|
||||
self.durationNode?.status = .single(nil)
|
||||
|
|
|
|||
|
|
@ -14,12 +14,13 @@ final class ChatSendMessageActionSheetController: ViewController {
|
|||
}
|
||||
|
||||
private let context: AccountContext
|
||||
private let controllerInteraction: ChatControllerInteraction?
|
||||
private let interfaceState: ChatPresentationInterfaceState
|
||||
private let gesture: ContextGesture
|
||||
private let sourceSendButton: ASDisplayNode
|
||||
private let textInputNode: EditableTextNode
|
||||
private let completion: () -> Void
|
||||
private let sendMessage: (Bool) -> Void
|
||||
private let schedule: () -> Void
|
||||
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
|
|
@ -29,15 +30,16 @@ final class ChatSendMessageActionSheetController: ViewController {
|
|||
|
||||
private let hapticFeedback = HapticFeedback()
|
||||
|
||||
init(context: AccountContext, controllerInteraction: ChatControllerInteraction?, interfaceState: ChatPresentationInterfaceState, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, completion: @escaping () -> Void) {
|
||||
init(context: AccountContext, interfaceState: ChatPresentationInterfaceState, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, completion: @escaping () -> Void, sendMessage: @escaping (Bool) -> Void, schedule: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.controllerInteraction = controllerInteraction
|
||||
self.interfaceState = interfaceState
|
||||
self.gesture = gesture
|
||||
self.sourceSendButton = sourceSendButton
|
||||
self.textInputNode = textInputNode
|
||||
self.completion = completion
|
||||
|
||||
self.sendMessage = sendMessage
|
||||
self.schedule = schedule
|
||||
|
||||
super.init(navigationBarPresentationData: nil)
|
||||
|
||||
self.blocksBackgroundWhenInOverlay = true
|
||||
|
|
@ -77,13 +79,13 @@ final class ChatSendMessageActionSheetController: ViewController {
|
|||
}
|
||||
|
||||
self.displayNode = ChatSendMessageActionSheetControllerNode(context: self.context, reminders: reminders, gesture: gesture, sourceSendButton: self.sourceSendButton, textInputNode: self.textInputNode, forwardedCount: forwardedCount, send: { [weak self] in
|
||||
self?.controllerInteraction?.sendCurrentMessage(false)
|
||||
self?.sendMessage(false)
|
||||
self?.dismiss(cancel: false)
|
||||
}, sendSilently: { [weak self] in
|
||||
self?.controllerInteraction?.sendCurrentMessage(true)
|
||||
self?.sendMessage(true)
|
||||
self?.dismiss(cancel: false)
|
||||
}, schedule: !canSchedule ? nil : { [weak self] in
|
||||
self?.controllerInteraction?.scheduleCurrentMessage()
|
||||
self?.schedule()
|
||||
self?.dismiss(cancel: false)
|
||||
}, cancel: { [weak self] in
|
||||
self?.dismiss(cancel: true)
|
||||
|
|
|
|||
|
|
@ -5649,32 +5649,32 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
|||
func forwardMessages(messageIds: Set<MessageId>?) {
|
||||
if let messageIds = messageIds ?? self.state.selectedMessageIds, !messageIds.isEmpty {
|
||||
let peerSelectionController = self.context.sharedContext.makePeerSelectionController(PeerSelectionControllerParams(context: self.context, filter: [.onlyWriteable, .excludeDisabled], multipleSelection: true))
|
||||
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, messageText in
|
||||
peerSelectionController.multiplePeersSelected = { [weak self, weak peerSelectionController] peers, messageText, mode in
|
||||
guard let strongSelf = self, let strongController = peerSelectionController else {
|
||||
return
|
||||
}
|
||||
strongController.dismiss()
|
||||
|
||||
for peer in peers {
|
||||
var result: [EnqueueMessage] = []
|
||||
if messageText.string.count > 0 {
|
||||
let inputText = convertMarkdownToAttributes(messageText)
|
||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||
if text.length != 0 {
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
|
||||
var result: [EnqueueMessage] = []
|
||||
if messageText.string.count > 0 {
|
||||
let inputText = convertMarkdownToAttributes(messageText)
|
||||
for text in breakChatInputText(trimChatInputText(inputText)) {
|
||||
if text.length != 0 {
|
||||
var attributes: [MessageAttribute] = []
|
||||
let entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text))
|
||||
if !entities.isEmpty {
|
||||
attributes.append(TextEntitiesMessageAttribute(entities: entities))
|
||||
}
|
||||
result.append(.message(text: text.string, attributes: attributes, mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil))
|
||||
}
|
||||
}
|
||||
|
||||
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
|
||||
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
result.append(contentsOf: messageIds.map { messageId -> EnqueueMessage in
|
||||
return .forward(source: messageId, grouping: .auto, attributes: [], correlationId: nil)
|
||||
})
|
||||
|
||||
for peer in peers {
|
||||
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peer.id, messages: result)
|
||||
|> deliverOnMainQueue).start(next: { messageIds in
|
||||
if let strongSelf = self {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
|
|||
private var customTitle: String?
|
||||
|
||||
public var peerSelected: ((Peer) -> Void)?
|
||||
public var multiplePeersSelected: (([Peer], NSAttributedString) -> Void)?
|
||||
public var multiplePeersSelected: (([Peer], NSAttributedString, PeerSelectionControllerSendMode) -> Void)?
|
||||
private let filter: ChatListNodePeersFilter
|
||||
|
||||
private let attemptSelection: ((Peer) -> Void)?
|
||||
|
|
@ -150,14 +150,16 @@ public final class PeerSelectionControllerImpl: ViewController, PeerSelectionCon
|
|||
override public func loadDisplayNode() {
|
||||
self.displayNode = PeerSelectionControllerNode(context: self.context, filter: self.filter, hasChatListSelector: self.hasChatListSelector, hasContactSelector: self.hasContactSelector, hasGlobalSearch: self.hasGlobalSearch, createNewGroup: self.createNewGroup, present: { [weak self] c, a in
|
||||
self?.present(c, in: .window(.root), with: a)
|
||||
}, presentInGlobalOverlay: { [weak self] c, a in
|
||||
self?.presentInGlobalOverlay(c, with: a)
|
||||
}, dismiss: { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
})
|
||||
|
||||
self.peerSelectionNode.navigationBar = self.navigationBar
|
||||
|
||||
self.peerSelectionNode.requestSend = { [weak self] peers, text in
|
||||
self?.multiplePeersSelected?(peers, text)
|
||||
self.peerSelectionNode.requestSend = { [weak self] peers, text, mode in
|
||||
self?.multiplePeersSelected?(peers, text, mode)
|
||||
}
|
||||
|
||||
self.peerSelectionNode.requestDeactivateSearch = { [weak self] in
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import SegmentedControlNode
|
|||
final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
private let context: AccountContext
|
||||
private let present: (ViewController, Any?) -> Void
|
||||
private let presentInGlobalOverlay: (ViewController, Any?) -> Void
|
||||
private let dismiss: () -> Void
|
||||
private let filter: ChatListNodePeersFilter
|
||||
private let hasGlobalSearch: Bool
|
||||
|
|
@ -55,7 +56,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||
var requestOpenDisabledPeer: ((Peer) -> Void)?
|
||||
var requestOpenPeerFromSearch: ((Peer) -> Void)?
|
||||
var requestOpenMessageFromSearch: ((Peer, MessageId) -> Void)?
|
||||
var requestSend: (([Peer], NSAttributedString) -> Void)?
|
||||
var requestSend: (([Peer], NSAttributedString, PeerSelectionControllerSendMode) -> Void)?
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
|
@ -65,9 +66,10 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||
return self.readyValue.get()
|
||||
}
|
||||
|
||||
init(context: AccountContext, filter: ChatListNodePeersFilter, hasChatListSelector: Bool, hasContactSelector: Bool, hasGlobalSearch: Bool, createNewGroup: (() -> Void)?, present: @escaping (ViewController, Any?) -> Void, dismiss: @escaping () -> Void) {
|
||||
init(context: AccountContext, filter: ChatListNodePeersFilter, hasChatListSelector: Bool, hasContactSelector: Bool, hasGlobalSearch: Bool, createNewGroup: (() -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, dismiss: @escaping () -> Void) {
|
||||
self.context = context
|
||||
self.present = present
|
||||
self.presentInGlobalOverlay = presentInGlobalOverlay
|
||||
self.dismiss = dismiss
|
||||
self.filter = filter
|
||||
self.hasGlobalSearch = hasGlobalSearch
|
||||
|
|
@ -266,7 +268,32 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||
}, openLinkEditing: {
|
||||
}, reportPeerIrrelevantGeoLocation: {
|
||||
}, displaySlowmodeTooltip: { _, _ in
|
||||
}, displaySendMessageOptions: { _, _ in
|
||||
}, displaySendMessageOptions: { [weak self] node, gesture in
|
||||
guard let strongSelf = self, let textInputPanelNode = strongSelf.textInputPanelNode else {
|
||||
return
|
||||
}
|
||||
textInputPanelNode.loadTextInputNodeIfNeeded()
|
||||
guard let textInputNode = textInputPanelNode.textInputNode else {
|
||||
return
|
||||
}
|
||||
// let previousSupportedOrientations = strongSelf.supportedOrientations
|
||||
// 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, interfaceState: strongSelf.presentationInterfaceState, gesture: gesture, sourceSendButton: node, textInputNode: textInputNode, completion: { [weak self] in
|
||||
if let strongSelf = self {
|
||||
// strongSelf.supportedOrientations = previousSupportedOrientations
|
||||
}
|
||||
}, sendMessage: { [weak textInputPanelNode] silently in
|
||||
textInputPanelNode?.sendMessage(silently ? .silent : .generic)
|
||||
}, schedule: { [weak textInputPanelNode] in
|
||||
textInputPanelNode?.sendMessage(.schedule)
|
||||
})
|
||||
// strongSelf.sendMessageActionsController = controller
|
||||
strongSelf.presentInGlobalOverlay(controller, nil)
|
||||
}, openScheduledMessages: {
|
||||
}, openPeersNearby: {
|
||||
}, displaySearchResultsTooltip: { _, _ in
|
||||
|
|
@ -311,7 +338,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||
} else {
|
||||
let textInputPanelNode = PeerSelectionTextInputPanelNode(presentationInterfaceState: self.presentationInterfaceState, presentController: { [weak self] c in self?.present(c, nil) })
|
||||
textInputPanelNode.interfaceInteraction = self.interfaceInteraction
|
||||
textInputPanelNode.sendMessage = { [weak self] in
|
||||
textInputPanelNode.sendMessage = { [weak self] mode in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
|
@ -327,7 +354,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
if !selectedPeers.isEmpty {
|
||||
strongSelf.requestSend?(selectedPeers, effectiveInputText)
|
||||
strongSelf.requestSend?(selectedPeers, effectiveInputText, mode)
|
||||
}
|
||||
} else {
|
||||
var selectedPeerIds: [PeerId] = []
|
||||
|
|
@ -345,7 +372,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
|||
selectedPeers.append(peer)
|
||||
}
|
||||
}
|
||||
strongSelf.requestSend?(selectedPeers, effectiveInputText)
|
||||
strongSelf.requestSend?(selectedPeers, effectiveInputText, mode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ class PeerSelectionTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDel
|
|||
|
||||
private var validLayout: (CGFloat, CGFloat, CGFloat, UIEdgeInsets, CGFloat, LayoutMetrics, Bool)?
|
||||
|
||||
var sendMessage: () -> Void = { }
|
||||
var sendMessage: (PeerSelectionControllerSendMode) -> Void = { _ in }
|
||||
var updateHeight: (Bool) -> Void = { _ in }
|
||||
|
||||
private var updatingInputState = false
|
||||
|
|
@ -896,7 +896,7 @@ class PeerSelectionTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDel
|
|||
}
|
||||
}
|
||||
|
||||
self.sendMessage()
|
||||
self.sendMessage(.generic)
|
||||
}
|
||||
|
||||
@objc func textInputBackgroundViewTap(_ recognizer: UITapGestureRecognizer) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue