From b778c66226773295ad16b7b539c1267967f3ccd9 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 20 Sep 2021 23:07:38 +0300 Subject: [PATCH] Refactoring --- .../Sources/CallListController.swift | 2 +- .../Sources/ChatListController.swift | 10 +- .../Sources/ChatListSearchContainerNode.swift | 4 +- .../Sources/Node/ChatListItemStrings.swift | 8 +- .../Sources/ContactsControllerNode.swift | 2 +- submodules/ContextUI/BUILD | 1 - .../ContextUI/Sources/ContextController.swift | 201 +------ .../ContextUI/Sources/PinchController.swift | 1 - .../GalleryData/Sources/GalleryData.swift | 6 +- .../ChatItemGalleryFooterContentNode.swift | 4 +- .../Items/UniversalVideoGalleryItem.swift | 2 +- .../SecretMediaPreviewController.swift | 2 +- .../Sources/InviteLinkInviteController.swift | 2 +- .../Sources/InviteLinkListController.swift | 4 +- .../Sources/InviteLinkViewController.swift | 2 +- .../Sources/ChannelVisibilityController.swift | 2 +- submodules/PeersNearbyUI/BUILD | 1 - .../Sources/PeersNearbyController.swift | 66 +-- submodules/ReactionSelectionNode/BUILD | 24 - .../Sources/ReactionAttachedNode.swift | 323 ----------- .../Sources/ReactionContextNode.swift | 523 ------------------ .../Sources/ReactionGestureItem.swift | 8 - .../Sources/ReactionSelectionNode.swift | 487 ---------------- .../Sources/ReactionSelectionParentNode.swift | 85 --- .../ReactionSwipeGestureRecognizer.swift | 193 ------- submodules/SelectablePeerNode/BUILD | 1 - .../Themes/ThemeSettingsController.swift | 4 +- submodules/SlotMachineAnimationNode/BUILD | 1 - .../Sources/SlotMachineAnimationNode.swift | 1 - .../Sources/ChannelStatsController.swift | 2 +- .../Sources/StatsMessageItem.swift | 2 +- .../MediaNavigationAccessoryHeaderNode.swift | 2 +- .../Sources/VoiceChatController.swift | 4 +- .../Sources/Account/Account.swift | 1 - .../Account/AccountIntermediateState.swift | 4 - .../ApiUtils/ReactionsMessageAttribute.swift | 101 ---- .../ApiUtils/StoreMessage_Telegram.swift | 4 - .../PendingMessages/EnqueueMessage.swift | 2 +- .../State/AccountStateManagementUtils.swift | 22 - .../Sources/State/AccountViewTracker.swift | 83 --- .../Sources/State/MessageReactions.swift | 227 -------- .../SyncCore_ReactionsMessageAttribute.swift | 31 +- .../TelegramEngine/Messages/Media.swift | 80 +++ .../Sources/Utils/PeerUtils.swift | 6 +- submodules/TelegramPermissions/BUILD | 1 - .../Sources/Permission.swift | 1 - submodules/TelegramStringFormatting/BUILD | 1 - .../Sources/MessageContentKind.swift | 29 +- .../Sources/ServiceMessageStrings.swift | 47 +- submodules/TelegramUI/BUILD | 1 - .../TelegramUI/Sources/ChatController.swift | 120 +--- .../Sources/ChatControllerInteraction.swift | 16 - .../Sources/ChatControllerNode.swift | 11 - .../Sources/ChatHistoryListNode.swift | 14 - .../Sources/ChatMediaInputNode.swift | 2 +- .../Sources/ChatMessageActionItemNode.swift | 2 +- .../ChatMessageAnimatedStickerItemNode.swift | 30 +- .../ChatMessageAttachedContentNode.swift | 25 +- .../ChatMessageBubbleContentNode.swift | 4 - .../Sources/ChatMessageBubbleItemNode.swift | 302 +--------- .../ChatMessageCallBubbleContentNode.swift | 6 +- .../ChatMessageContactBubbleContentNode.swift | 24 +- .../ChatMessageDateAndStatusNode.swift | 276 +-------- .../ChatMessageFileBubbleContentNode.swift | 4 - .../ChatMessageGameBubbleContentNode.swift | 4 - .../ChatMessageInstantVideoItemNode.swift | 4 - .../ChatMessageInteractiveFileNode.swift | 24 +- ...atMessageInteractiveInstantVideoNode.swift | 17 +- .../ChatMessageInteractiveMediaNode.swift | 3 +- .../ChatMessageInvoiceBubbleContentNode.swift | 4 - .../ChatMessageMapBubbleContentNode.swift | 24 +- .../ChatMessageMediaBubbleContentNode.swift | 23 +- .../Sources/ChatMessageNotificationItem.swift | 28 +- .../ChatMessagePollBubbleContentNode.swift | 24 +- .../Sources/ChatMessageReplyInfoNode.swift | 2 +- ...atMessageRestrictedBubbleContentNode.swift | 24 +- .../Sources/ChatMessageStickerItemNode.swift | 30 +- .../Sources/ChatMessageSwipeToReplyNode.swift | 4 - .../ChatMessageTextBubbleContentNode.swift | 31 +- .../ChatMessageWebpageBubbleContentNode.swift | 4 - .../ChatPinnedMessageTitlePanelNode.swift | 2 +- .../ChatRecentActionsControllerNode.swift | 4 - .../ChatSearchResultsContollerNode.swift | 2 +- .../Sources/DrawingStickersScreen.swift | 4 - .../Sources/EditAccessoryPanelNode.swift | 4 +- .../OverlayAudioPlayerControllerNode.swift | 4 - .../Sources/PeerInfo/PeerInfoScreen.swift | 24 +- .../Sources/ReplyAccessoryPanelNode.swift | 4 +- .../Sources/SharedAccountContext.swift | 4 - .../StringForMessageTimestampStatus.swift | 2 +- .../WebpagePreviewAccessoryPanelNode.swift | 2 +- 91 files changed, 290 insertions(+), 3473 deletions(-) delete mode 100644 submodules/ReactionSelectionNode/BUILD delete mode 100644 submodules/ReactionSelectionNode/Sources/ReactionAttachedNode.swift delete mode 100644 submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift delete mode 100644 submodules/ReactionSelectionNode/Sources/ReactionGestureItem.swift delete mode 100644 submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift delete mode 100644 submodules/ReactionSelectionNode/Sources/ReactionSelectionParentNode.swift delete mode 100644 submodules/ReactionSelectionNode/Sources/ReactionSwipeGestureRecognizer.swift delete mode 100644 submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift delete mode 100644 submodules/TelegramCore/Sources/State/MessageReactions.swift diff --git a/submodules/CallListUI/Sources/CallListController.swift b/submodules/CallListUI/Sources/CallListController.swift index 2c18b5e7ea..a9ce802c2e 100644 --- a/submodules/CallListUI/Sources/CallListController.swift +++ b/submodules/CallListUI/Sources/CallListController.swift @@ -358,7 +358,7 @@ public final class CallListController: TelegramBaseController { } } - let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .extracted(ExtractedContentSourceImpl(controller: self, sourceNode: buttonNode.contentNode, keepInPlace: false, blurBackground: false)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: nil) + let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .extracted(ExtractedContentSourceImpl(controller: self, sourceNode: buttonNode.contentNode, keepInPlace: false, blurBackground: false)), items: .single(ContextController.Items(items: items)), gesture: nil) self.presentInGlobalOverlay(contextController) } diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index fdb3d251ab..3a09af35c9 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -839,12 +839,12 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController case let .groupReference(groupId, _, _, _, _): let chatListController = ChatListControllerImpl(context: strongSelf.context, groupId: groupId, controlsHistoryPreload: false, hideNetworkActivityStatus: true, previewing: true, enableDebugActions: false) chatListController.navigationPresentation = .master - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: archiveContextMenuItems(context: strongSelf.context, groupId: groupId, chatListController: strongSelf) |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: archiveContextMenuItems(context: strongSelf.context, groupId: groupId, chatListController: strongSelf) |> map { ContextController.Items(items: $0) }, gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) case let .peer(_, peer, _, _, _, _, _, _, promoInfo, _, _, _): let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.peerId), subject: nil, botStart: nil, mode: .standard(previewing: true)) chatController.canReadHistory.set(false) - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.peerId, promoInfo: promoInfo, source: .chatList(filter: strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter), chatListController: strongSelf, joined: joined) |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)), items: chatContextMenuItems(context: strongSelf.context, peerId: peer.peerId, promoInfo: promoInfo, source: .chatList(filter: strongSelf.chatListDisplayNode.containerNode.currentItemNode.chatListFilter), chatListController: strongSelf, joined: joined) |> map { ContextController.Items(items: $0) }, gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) } } @@ -868,7 +868,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController contextContentSource = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController)) } - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: contextContentSource, items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: nil, source: .search(source), chatListController: strongSelf, joined: false) |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: contextContentSource, items: chatContextMenuItems(context: strongSelf.context, peerId: peer.id, promoInfo: nil, source: .search(source), chatListController: strongSelf, joined: false) |> map { ContextController.Items(items: $0) }, gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) } @@ -1095,7 +1095,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController }))) } - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatListHeaderBarContextExtractedContentSource(controller: strongSelf, sourceNode: sourceNode, keepInPlace: keepInPlace)), items: .single(ContextController.Items(items: items)), reactionItems: [], recognizer: nil, gesture: gesture) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatListHeaderBarContextExtractedContentSource(controller: strongSelf, sourceNode: sourceNode, keepInPlace: keepInPlace)), items: .single(ContextController.Items(items: items)), recognizer: nil, gesture: gesture) strongSelf.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller) }) } @@ -2842,7 +2842,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } } - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatListTabBarContextExtractedContentSource(controller: strongSelf, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), reactionItems: [], recognizer: nil, gesture: gesture) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatListTabBarContextExtractedContentSource(controller: strongSelf, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), recognizer: nil, gesture: gesture) strongSelf.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller) }) } diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 653800451a..49be4fa6eb 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -737,7 +737,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo return items } - let controller = ContextController(account: self.context.account, presentationData: self.presentationData, source: .extracted(MessageContextExtractedContentSource(sourceNode: node)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], recognizer: nil, gesture: gesture) + let controller = ContextController(account: self.context.account, presentationData: self.presentationData, source: .extracted(MessageContextExtractedContentSource(sourceNode: node)), items: items |> map { ContextController.Items(items: $0) }, recognizer: nil, gesture: gesture) self.presentInGlobalOverlay?(controller, nil) } @@ -797,7 +797,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo switch previewData { case let .gallery(gallery): gallery.setHintWillBePresentedInPreviewingContext(true) - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceNode: node)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceNode: node)), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) strongSelf.presentInGlobalOverlay?(contextController, nil) case .instantPage: break diff --git a/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift b/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift index c55ebd95b6..dcae9682c3 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItemStrings.swift @@ -53,8 +53,8 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: var hideAuthor = false var messageText: String if let message = message { - if let messageMain = messageMainPeer(message) { - peer = messageMain + if let messageMain = messageMainPeer(EngineMessage(message)) { + peer = messageMain._asPeer() } else { peer = chatPeer.chatMainPeer } @@ -261,12 +261,12 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: } default: hideAuthor = true - if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) { + if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), accountPeerId: accountPeerId, forChatList: true) { messageText = text } } case _ as TelegramMediaExpiredContent: - if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) { + if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), accountPeerId: accountPeerId, forChatList: true) { messageText = text } case let poll as TelegramMediaPoll: diff --git a/submodules/ContactListUI/Sources/ContactsControllerNode.swift b/submodules/ContactListUI/Sources/ContactsControllerNode.swift index fa8f33eb82..ed873ef808 100644 --- a/submodules/ContactListUI/Sources/ContactsControllerNode.swift +++ b/submodules/ContactListUI/Sources/ContactsControllerNode.swift @@ -175,7 +175,7 @@ final class ContactsControllerNode: ASDisplayNode { } let chatController = self.context.sharedContext.makeChatController(context: self.context, chatLocation: .peer(peer.id), subject: nil, botStart: nil, mode: .standard(previewing: true)) chatController.canReadHistory.set(false) - let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: contactContextMenuItems(context: self.context, peerId: peer.id, contactsController: contactsController) |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: contactContextMenuItems(context: self.context, peerId: peer.id, contactsController: contactsController) |> map { ContextController.Items(items: $0) }, gesture: gesture) contactsController.presentInGlobalOverlay(contextController) } diff --git a/submodules/ContextUI/BUILD b/submodules/ContextUI/BUILD index 8f1126f0c8..df3cad27f7 100644 --- a/submodules/ContextUI/BUILD +++ b/submodules/ContextUI/BUILD @@ -15,7 +15,6 @@ swift_library( "//submodules/Display:Display", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/TextSelectionNode:TextSelectionNode", - "//submodules/ReactionSelectionNode:ReactionSelectionNode", "//submodules/AppBundle:AppBundle", ], visibility = [ diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index b6eebef7c0..dfa5bfbf5c 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import Display import TelegramPresentationData import TextSelectionNode -import ReactionSelectionNode import TelegramCore import SwiftSignalKit @@ -119,7 +118,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi private let source: ContextContentSource private var items: Signal private let beginDismiss: (ContextMenuActionResult) -> Void - private let reactionSelected: (ReactionContextItem.Reaction) -> Void private let beganAnimatingOut: () -> Void private let attemptTransitionControllerIntoNavigation: () -> Void fileprivate var dismissedForCancel: (() -> Void)? @@ -150,14 +148,11 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi private var contentAreaInScreenSpace: CGRect? private let contentContainerNode: ContextContentContainerNode private var actionsContainerNode: ContextActionsContainerNode - private var reactionContextNode: ReactionContextNode? - private var reactionContextNodeIsAnimatingOut = false private var didCompleteAnimationIn = false private var initialContinueGesturePoint: CGPoint? private var didMoveFromInitialGesturePoint = false private var highlightedActionNode: ContextActionNodeProtocol? - private var highlightedReaction: ReactionContextItem.Reaction? private let hapticFeedback = HapticFeedback() @@ -168,12 +163,11 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi private let blurBackground: Bool - init(account: Account, controller: ContextController, presentationData: PresentationData, source: ContextContentSource, items: Signal, reactionItems: [ReactionContextItem], beginDismiss: @escaping (ContextMenuActionResult) -> Void, recognizer: TapLongTapOrDoubleTapGestureRecognizer?, gesture: ContextGesture?, reactionSelected: @escaping (ReactionContextItem.Reaction) -> Void, beganAnimatingOut: @escaping () -> Void, attemptTransitionControllerIntoNavigation: @escaping () -> Void) { + init(account: Account, controller: ContextController, presentationData: PresentationData, source: ContextContentSource, items: Signal, beginDismiss: @escaping (ContextMenuActionResult) -> Void, recognizer: TapLongTapOrDoubleTapGestureRecognizer?, gesture: ContextGesture?, beganAnimatingOut: @escaping () -> Void, attemptTransitionControllerIntoNavigation: @escaping () -> Void) { self.presentationData = presentationData self.source = source self.items = items self.beginDismiss = beginDismiss - self.reactionSelected = reactionSelected self.beganAnimatingOut = beganAnimatingOut self.attemptTransitionControllerIntoNavigation = attemptTransitionControllerIntoNavigation self.gesture = gesture @@ -237,13 +231,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi feedbackTap?() }, blurBackground: blurBackground) - if !reactionItems.isEmpty { - let reactionContextNode = ReactionContextNode(account: account, theme: presentationData.theme, items: reactionItems) - self.reactionContextNode = reactionContextNode - } else { - self.reactionContextNode = nil - } - super.init() feedbackTap = { [weak self] in @@ -265,7 +252,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi self.scrollNode.addSubnode(self.dismissAccessibilityArea) self.scrollNode.addSubnode(self.actionsContainerNode) - self.reactionContextNode.flatMap(self.addSubnode) if let recognizer = recognizer { recognizer.externalUpdated = { [weak self, weak recognizer] view, point in @@ -298,24 +284,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.hapticFeedback.tap() } } - - if let reactionContextNode = strongSelf.reactionContextNode { - let highlightedReaction = reactionContextNode.reaction(at: strongSelf.view.convert(localPoint, to: reactionContextNode.view)).flatMap { value -> ReactionContextItem.Reaction? in - switch value { - case .like: - return .like - case .unlike: - return .unlike - } - } - if strongSelf.highlightedReaction != highlightedReaction { - strongSelf.highlightedReaction = highlightedReaction - reactionContextNode.setHighlightedReaction(highlightedReaction) - if let _ = highlightedReaction { - strongSelf.hapticFeedback.tap() - } - } - } } } } @@ -330,20 +298,11 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.highlightedActionNode = nil highlightedActionNode.performAction() } - if let _ = strongSelf.reactionContextNode { - if let reaction = strongSelf.highlightedReaction { - strongSelf.reactionSelected(reaction) - } - } } else { if let highlightedActionNode = strongSelf.highlightedActionNode { strongSelf.highlightedActionNode = nil highlightedActionNode.setIsHighlighted(false) } - if let reactionContextNode = strongSelf.reactionContextNode, let _ = strongSelf.highlightedReaction { - strongSelf.highlightedReaction = nil - reactionContextNode.setHighlightedReaction(nil) - } } } } @@ -382,24 +341,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.hapticFeedback.tap() } } - - if let reactionContextNode = strongSelf.reactionContextNode { - let highlightedReaction = reactionContextNode.reaction(at: strongSelf.view.convert(localPoint, to: reactionContextNode.view)).flatMap { value -> ReactionContextItem.Reaction? in - switch value { - case .like: - return .like - case .unlike: - return .unlike - } - } - if strongSelf.highlightedReaction != highlightedReaction { - strongSelf.highlightedReaction = highlightedReaction - reactionContextNode.setHighlightedReaction(highlightedReaction) - if let _ = highlightedReaction { - strongSelf.hapticFeedback.tap() - } - } - } } } } @@ -414,39 +355,16 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.highlightedActionNode = nil highlightedActionNode.performAction() } - if let _ = strongSelf.reactionContextNode { - if let reaction = strongSelf.highlightedReaction { - strongSelf.reactionSelected(reaction) - } - } } else { if let highlightedActionNode = strongSelf.highlightedActionNode { strongSelf.highlightedActionNode = nil highlightedActionNode.setIsHighlighted(false) } - if let reactionContextNode = strongSelf.reactionContextNode, let _ = strongSelf.highlightedReaction { - strongSelf.highlightedReaction = nil - reactionContextNode.setHighlightedReaction(nil) - } } } } } - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.reactionSelected = { [weak self] reaction in - guard let _ = self else { - return - } - switch reaction { - case .like: - reactionSelected(.like) - case .unlike: - reactionSelected(.unlike) - } - } - } - self.itemsDisposable.set((items |> deliverOnMainQueue).start(next: { [weak self] items in self?.setItems(items: items, minHeight: nil, previousActionsTransition: .scale) @@ -527,26 +445,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi strongSelf.updateLayout(layout: validLayout, transition: .animated(duration: 0.2 * animationDurationFactor, curve: .easeInOut), previousActionsContainerNode: nil) } } - takenViewInfo.contentContainingNode.updateDistractionFreeMode = { [weak self] value in - guard let strongSelf = self, let reactionContextNode = strongSelf.reactionContextNode else { - return - } - if value { - if !reactionContextNode.alpha.isZero { - reactionContextNode.alpha = 0.0 - reactionContextNode.allowsGroupOpacity = true - reactionContextNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3 * animationDurationFactor, completion: { [weak reactionContextNode] _ in - reactionContextNode?.allowsGroupOpacity = false - }) - } - } else if reactionContextNode.alpha != 1.0 { - reactionContextNode.alpha = 1.0 - reactionContextNode.allowsGroupOpacity = true - reactionContextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3 * animationDurationFactor, completion: { [weak reactionContextNode] _ in - reactionContextNode?.allowsGroupOpacity = false - }) - } - } self.contentAreaInScreenSpace = takenViewInfo.contentAreaInScreenSpace self.contentContainerNode.addSubnode(takenViewInfo.contentContainingNode.contentNode) @@ -695,10 +593,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi localContentSourceFrame = localSourceFrame } - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateIn(from: CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalProjectedContentViewFrame.1.minY), size: contentParentNode.contentRect.size)) - } - self.actionsContainerNode.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: localSourceFrame.center.x - self.actionsContainerNode.position.x, y: localSourceFrame.center.y - self.actionsContainerNode.position.y + actionsOffset)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: actionsDuration, initialVelocity: 0.0, damping: springDamping, additive: true) let contentContainerOffset = CGPoint(x: localContentSourceFrame.center.x - self.contentContainerNode.frame.center.x - contentParentNode.contentRect.minX, y: localContentSourceFrame.center.y - self.contentContainerNode.frame.center.y - contentParentNode.contentRect.minY) self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: contentContainerOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: contentDuration, initialVelocity: 0.0, damping: springDamping, additive: true, completion: { [weak self] _ in @@ -968,10 +862,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi contentParentNode.updateAbsoluteRect?(self.contentContainerNode.frame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y + contentContainerOffset.y), self.bounds.size) contentParentNode.applyAbsoluteOffset?(CGPoint(x: 0.0, y: -contentContainerOffset.y), transitionCurve, transitionDuration) - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateOut(to: CGRect(origin: CGPoint(x: originalProjectedContentViewFrame.1.minX, y: originalProjectedContentViewFrame.1.minY), size: contentParentNode.contentRect.size), animatingOutToReaction: self.reactionContextNodeIsAnimatingOut) - } - contentParentNode.willUpdateIsExtractedToContextPreview?(false, .animated(duration: 0.2, curve: .easeInOut)) } else { if let snapshotView = contentParentNode.contentNode.view.snapshotContentTree(keepTransform: true) { @@ -990,10 +880,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi contentParentNode.contentNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) contentParentNode.willUpdateIsExtractedToContextPreview?(false, .animated(duration: 0.2, curve: .easeInOut)) - - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateOut(to: nil, animatingOutToReaction: self.reactionContextNodeIsAnimatingOut) - } } case let .controller(source): guard let maybeContentNode = self.contentContainerNode.contentNode, case let .controller(controller) = maybeContentNode else { @@ -1132,42 +1018,9 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi completedContentNode = true intermediateCompletion() }) - - if let reactionContextNode = self.reactionContextNode { - reactionContextNode.animateOut(to: nil, animatingOutToReaction: self.reactionContextNodeIsAnimatingOut) - } } } } - - func animateOutToReaction(value: String, targetEmptyNode: ASDisplayNode, targetFilledNode: ASDisplayNode, hideNode: Bool, completion: @escaping () -> Void) { - guard let reactionContextNode = self.reactionContextNode else { - self.animateOut(result: .default, completion: completion) - return - } - var contentCompleted = false - var reactionCompleted = false - let intermediateCompletion: () -> Void = { - if contentCompleted && reactionCompleted { - completion() - } - } - - self.reactionContextNodeIsAnimatingOut = true - self.animateOut(result: .default, completion: { - contentCompleted = true - intermediateCompletion() - }) - reactionContextNode.animateOutToReaction(value: value, targetEmptyNode: targetEmptyNode, targetFilledNode: targetFilledNode, hideNode: hideNode, completion: { [weak self] in - guard let strongSelf = self else { - return - } - strongSelf.reactionContextNode?.removeFromSupernode() - strongSelf.reactionContextNode = nil - reactionCompleted = true - intermediateCompletion() - }) - } func getActionsMinHeight() -> ContextController.ActionsHeight? { if !self.actionsContainerNode.bounds.height.isZero { @@ -1281,10 +1134,8 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi transition.updateFrame(node: self.scrollNode, frame: CGRect(origin: CGPoint(), size: layout.size)) let actionsSideInset: CGFloat = layout.safeInsets.left + 11.0 - var contentTopInset: CGFloat = max(11.0, layout.statusBarHeight ?? 0.0) - if let _ = self.reactionContextNode { - contentTopInset += 34.0 - } + let contentTopInset: CGFloat = max(11.0, layout.statusBarHeight ?? 0.0) + let actionsBottomInset: CGFloat = 11.0 if let contentNode = self.contentContainerNode.contentNode { @@ -1506,12 +1357,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi let absoluteContentRect = contentContainerFrame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y) contentParentNode.updateAbsoluteRect?(absoluteContentRect, layout.size) - - if let reactionContextNode = self.reactionContextNode { - let insets = layout.insets(options: [.statusBar]) - transition.updateFrame(node: reactionContextNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - reactionContextNode.updateLayout(size: layout.size, insets: insets, anchorRect: CGRect(origin: CGPoint(x: absoluteContentRect.minX + contentParentNode.contentRect.minX, y: absoluteContentRect.minY + contentParentNode.contentRect.minY), size: contentParentNode.contentRect.size), transition: transition) - } } case let .controller(contentParentNode): var projectedFrame: CGRect = convertFrame(contentParentNode.sourceNode.bounds, from: contentParentNode.sourceNode.view, to: self.view) @@ -1642,14 +1487,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi transition.animateOffsetAdditive(node: self.scrollNode, offset: currentContainerFrame.minY - previousContainerFrame.minY) } } - - let absoluteContentRect = contentContainerFrame.offsetBy(dx: 0.0, dy: -self.scrollNode.view.contentOffset.y) - - if let reactionContextNode = self.reactionContextNode { - let insets = layout.insets(options: [.statusBar]) - transition.updateFrame(node: reactionContextNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - reactionContextNode.updateLayout(size: layout.size, insets: insets, anchorRect: CGRect(origin: CGPoint(x: absoluteContentRect.minX, y: absoluteContentRect.minY), size: contentSize), transition: transition) - } } } } @@ -1734,11 +1571,6 @@ private final class ContextControllerNode: ViewControllerTracingNode, UIScrollVi if !self.bounds.contains(point) { return nil } - if let reactionContextNode = self.reactionContextNode { - if let result = reactionContextNode.hitTest(self.view.convert(point, to: reactionContextNode.view), with: event) { - return result - } - } let mappedPoint = self.view.convert(point, to: self.scrollNode.view) if let maybeContentNode = self.contentContainerNode.contentNode { switch maybeContentNode { @@ -1918,7 +1750,6 @@ public final class ContextController: ViewController, StandalonePresentableContr private var presentationData: PresentationData private let source: ContextContentSource private var items: Signal - private var reactionItems: [ReactionContextItem] private let _ready = Promise() override public var ready: Promise { @@ -1934,8 +1765,7 @@ public final class ContextController: ViewController, StandalonePresentableContr private var controllerNode: ContextControllerNode { return self.displayNode as! ContextControllerNode } - - public var reactionSelected: ((ReactionContextItem.Reaction) -> Void)? + public var dismissed: (() -> Void)? public var dismissedForCancel: (() -> Void)? { didSet { @@ -1948,12 +1778,11 @@ public final class ContextController: ViewController, StandalonePresentableContr private var shouldBeDismissedDisposable: Disposable? - public init(account: Account, presentationData: PresentationData, source: ContextContentSource, items: Signal, reactionItems: [ReactionContextItem], recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil) { + public init(account: Account, presentationData: PresentationData, source: ContextContentSource, items: Signal, recognizer: TapLongTapOrDoubleTapGestureRecognizer? = nil, gesture: ContextGesture? = nil) { self.account = account self.presentationData = presentationData self.source = source self.items = items - self.reactionItems = reactionItems self.recognizer = recognizer self.gesture = gesture @@ -2004,14 +1833,9 @@ public final class ContextController: ViewController, StandalonePresentableContr } override public func loadDisplayNode() { - self.displayNode = ContextControllerNode(account: self.account, controller: self, presentationData: self.presentationData, source: self.source, items: self.items, reactionItems: self.reactionItems, beginDismiss: { [weak self] result in + self.displayNode = ContextControllerNode(account: self.account, controller: self, presentationData: self.presentationData, source: self.source, items: self.items, beginDismiss: { [weak self] result in self?.dismiss(result: result, completion: nil) - }, recognizer: self.recognizer, gesture: self.gesture, reactionSelected: { [weak self] value in - guard let strongSelf = self else { - return - } - strongSelf.reactionSelected?(value) - }, beganAnimatingOut: { [weak self] in + }, recognizer: self.recognizer, gesture: self.gesture, beganAnimatingOut: { [weak self] in self?.statusBar.statusBarStyle = .Ignore }, attemptTransitionControllerIntoNavigation: { [weak self] in guard let strongSelf = self else { @@ -2096,15 +1920,4 @@ public final class ContextController: ViewController, StandalonePresentableContr override public func dismiss(completion: (() -> Void)? = nil) { self.dismiss(result: .default, completion: completion) } - - public func dismissWithReaction(value: String, targetEmptyNode: ASDisplayNode, targetFilledNode: ASDisplayNode, hideNode: Bool, completion: (() -> Void)?) { - if !self.wasDismissed { - self.wasDismissed = true - self.controllerNode.animateOutToReaction(value: value, targetEmptyNode: targetEmptyNode, targetFilledNode: targetFilledNode, hideNode: hideNode, completion: { [weak self] in - self?.presentingViewController?.dismiss(animated: false, completion: nil) - completion?() - }) - self.dismissed?() - } - } } diff --git a/submodules/ContextUI/Sources/PinchController.swift b/submodules/ContextUI/Sources/PinchController.swift index 8f2a93e12a..e7db5ab007 100644 --- a/submodules/ContextUI/Sources/PinchController.swift +++ b/submodules/ContextUI/Sources/PinchController.swift @@ -4,7 +4,6 @@ import AsyncDisplayKit import Display import TelegramPresentationData import TextSelectionNode -import ReactionSelectionNode import TelegramCore import SwiftSignalKit diff --git a/submodules/GalleryData/Sources/GalleryData.swift b/submodules/GalleryData/Sources/GalleryData.swift index 43632cd6ac..6820a64b07 100644 --- a/submodules/GalleryData/Sources/GalleryData.swift +++ b/submodules/GalleryData/Sources/GalleryData.swift @@ -97,9 +97,9 @@ public func chatMessageGalleryControllerData(context: AccountContext, chatLocati if let action = media as? TelegramMediaAction { switch action.action { case let .photoUpdated(image): - if let peer = messageMainPeer(message), let image = image { - let promise: Promise<[AvatarGalleryEntry]> = Promise([AvatarGalleryEntry.image(image.imageId, image.reference, image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(message), media: media), resource: $0.resource)) }), image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(message), media: media), resource: $0.resource)) }), peer, message.timestamp, nil, message.id, image.immediateThumbnailData, "action")]) - let galleryController = AvatarGalleryController(context: context, peer: peer, sourceCorners: .roundRect(15.5), remoteEntries: promise, skipInitial: true, replaceRootController: { controller, ready in + if let peer = messageMainPeer(EngineMessage(message)), let image = image { + let promise: Promise<[AvatarGalleryEntry]> = Promise([AvatarGalleryEntry.image(image.imageId, image.reference, image.representations.map({ ImageRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(message), media: media), resource: $0.resource)) }), image.videoRepresentations.map({ VideoRepresentationWithReference(representation: $0, reference: .media(media: .message(message: MessageReference(message), media: media), resource: $0.resource)) }), peer._asPeer(), message.timestamp, nil, message.id, image.immediateThumbnailData, "action")]) + let galleryController = AvatarGalleryController(context: context, peer: peer._asPeer(), sourceCorners: .roundRect(15.5), remoteEntries: promise, skipInitial: true, replaceRootController: { controller, ready in }) return .chatAvatars(galleryController, image) diff --git a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 5d62e2242b..9f0381b93b 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -954,7 +954,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll var generalMessageContentKind: MessageContentKind? for message in messages { - let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: message, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId) + let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId) if generalMessageContentKind == nil || generalMessageContentKind == currentKind { generalMessageContentKind = currentKind } else { @@ -1103,7 +1103,7 @@ final class ChatItemGalleryFooterContentNode: GalleryFooterContentNode, UIScroll var messageContentKinds = Set() for message in messages { - let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: message, strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId) + let currentKind = messageContentKind(contentSettings: strongSelf.context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: strongSelf.context.account.peerId) if beganContentKindScanning && currentKind != generalMessageContentKind { generalMessageContentKind = nil } else if !beganContentKindScanning || currentKind == generalMessageContentKind { diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 754c243979..b8bbf7064b 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -2032,7 +2032,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { return } - let contextController = ContextController(account: self.context.account, presentationData: self.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme), source: .reference(HeaderContextReferenceContentSource(controller: controller, sourceNode: self.moreBarButton.referenceNode)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: self.context.account, presentationData: self.presentationData.withUpdated(theme: defaultDarkColorPresentationTheme), source: .reference(HeaderContextReferenceContentSource(controller: controller, sourceNode: self.moreBarButton.referenceNode)), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) self.isShowingContextMenuPromise.set(true) controller.presentInGlobalOverlay(contextController) diff --git a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift index f0de0120e9..de83c7efb2 100644 --- a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift +++ b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift @@ -300,7 +300,7 @@ public final class SecretMediaPreviewController: ViewController { }, transition: .immediate) } else { let contentNode = SecretMediaPreviewFooterContentNode() - let peerTitle = messageMainPeer(message).flatMap(EnginePeer.init)?.compactDisplayTitle ?? "" + let peerTitle = messageMainPeer(EngineMessage(message))?.compactDisplayTitle ?? "" let text: String if let file = media as? TelegramMediaFile { if file.isAnimated { diff --git a/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift b/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift index f2d5a47df1..5f901ff199 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkInviteController.swift @@ -418,7 +418,7 @@ public final class InviteLinkInviteController: ViewController { }) }))) - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .reference(InviteLinkContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .reference(InviteLinkContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(items: items)), gesture: gesture) self?.controller?.presentInGlobalOverlay(contextController) }, copyLink: { [weak self] invite in UIPasteboard.general.string = invite.link diff --git a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift index 765e509835..14eb5afa78 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkListController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkListController.swift @@ -550,7 +550,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio }))) } - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .reference(InviteLinkContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .reference(InviteLinkContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(items: items)), gesture: gesture) presentInGlobalOverlayImpl?(contextController) }, createLink: { let controller = inviteLinkEditController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, invite: nil, completion: { invite in @@ -714,7 +714,7 @@ public func inviteLinkListController(context: AccountContext, updatedPresentatio }))) } - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node, blurBackground: true)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node, blurBackground: true)), items: .single(ContextController.Items(items: items)), gesture: gesture) presentInGlobalOverlayImpl?(contextController) }, openAdmin: { admin in let controller = inviteLinkListController(context: context, peerId: peerId, admin: admin) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift index dd42de62c0..54053c4597 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkViewController.swift @@ -565,7 +565,7 @@ public final class InviteLinkViewController: ViewController { }))) } - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .reference(InviteLinkContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .reference(InviteLinkContextReferenceContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(items: items)), gesture: gesture) self?.controller?.presentInGlobalOverlay(contextController) }) diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index 6d9e63b974..36fb8366b1 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -1050,7 +1050,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta }) }))) - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(InviteLinkContextExtractedContentSource(controller: controller, sourceNode: node)), items: .single(ContextController.Items(items: items)), gesture: gesture) presentInGlobalOverlayImpl?(contextController) }, manageInviteLinks: { let controller = inviteLinkListController(context: context, updatedPresentationData: updatedPresentationData, peerId: peerId, admin: nil) diff --git a/submodules/PeersNearbyUI/BUILD b/submodules/PeersNearbyUI/BUILD index a83643a764..4ebbdcdbb5 100644 --- a/submodules/PeersNearbyUI/BUILD +++ b/submodules/PeersNearbyUI/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/TelegramPresentationData:TelegramPresentationData", "//submodules/AccountContext:AccountContext", diff --git a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift index f89a075977..d140c63ae3 100644 --- a/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift +++ b/submodules/PeersNearbyUI/Sources/PeersNearbyController.swift @@ -3,7 +3,6 @@ import UIKit import AsyncDisplayKit import Display import SwiftSignalKit -import Postbox import TelegramCore import MapKit import TelegramPresentationData @@ -27,14 +26,15 @@ import TelegramStringFormatting private let maxUsersDisplayedLimit: Int32 = 5 private struct PeerNearbyEntry { - let peer: (Peer, CachedPeerData?) + let peer: EnginePeer + let memberCount: Int32? let expires: Int32 let distance: Int32 } private func arePeersNearbyEqual(_ lhs: PeerNearbyEntry?, _ rhs: PeerNearbyEntry?) -> Bool { if let lhs = lhs, let rhs = rhs { - return lhs.peer.0.isEqual(rhs.peer.0) && lhs.expires == rhs.expires && lhs.distance == rhs.distance + return lhs.peer == rhs.peer && lhs.expires == rhs.expires && lhs.distance == rhs.distance } else { return (lhs != nil) == (rhs != nil) } @@ -45,7 +45,7 @@ private func arePeerNearbyArraysEqual(_ lhs: [PeerNearbyEntry], _ rhs: [PeerNear return false } for i in 0 ..< lhs.count { - if !lhs[i].peer.0.isEqual(rhs[i].peer.0) || lhs[i].expires != rhs[i].expires || lhs[i].distance != rhs[i].distance { + if lhs[i].peer != rhs[i].peer || lhs[i].expires != rhs[i].expires || lhs[i].distance != rhs[i].distance { return false } } @@ -55,13 +55,13 @@ private func arePeerNearbyArraysEqual(_ lhs: [PeerNearbyEntry], _ rhs: [PeerNear private final class PeersNearbyControllerArguments { let context: AccountContext let toggleVisibility: (Bool) -> Void - let openProfile: (Peer, Int32) -> Void - let openChat: (Peer) -> Void + let openProfile: (EnginePeer, Int32) -> Void + let openChat: (EnginePeer) -> Void let openCreateGroup: (Double, Double, String?) -> Void - let contextAction: (Peer, ASDisplayNode, ContextGesture?) -> Void + let contextAction: (EnginePeer, ASDisplayNode, ContextGesture?) -> Void let expandUsers: () -> Void - init(context: AccountContext, toggleVisibility: @escaping (Bool) -> Void, openProfile: @escaping (Peer, Int32) -> Void, openChat: @escaping (Peer) -> Void, openCreateGroup: @escaping (Double, Double, String?) -> Void, contextAction: @escaping (Peer, ASDisplayNode, ContextGesture?) -> Void, expandUsers: @escaping () -> Void) { + init(context: AccountContext, toggleVisibility: @escaping (Bool) -> Void, openProfile: @escaping (EnginePeer, Int32) -> Void, openChat: @escaping (EnginePeer) -> Void, openCreateGroup: @escaping (Double, Double, String?) -> Void, contextAction: @escaping (EnginePeer, ASDisplayNode, ContextGesture?) -> Void, expandUsers: @escaping () -> Void) { self.context = context self.toggleVisibility = toggleVisibility self.openProfile = openProfile @@ -226,13 +226,13 @@ private enum PeersNearbyEntry: ItemListNodeEntry { }) case let .user(_, _, strings, dateTimeFormat, nameDisplayOrder, peer): var text = strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string - let isSelfPeer = peer.peer.0.id == arguments.context.account.peerId + let isSelfPeer = peer.peer.id == arguments.context.account.peerId if isSelfPeer { text = strings.PeopleNearby_VisibleUntil(humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: peer.expires).string).string } - return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: EnginePeer(peer.peer.0), aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: .text(text, .secondary), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: !isSelfPeer, sectionId: self.section, action: { + return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer.peer, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: .text(text, .secondary), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: !isSelfPeer, sectionId: self.section, action: { if !isSelfPeer { - arguments.openProfile(peer.peer.0, peer.distance) + arguments.openProfile(peer.peer, peer.distance) } }, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: nil, hasTopGroupInset: false, tag: nil) case let .expand(theme, title): @@ -249,29 +249,29 @@ private enum PeersNearbyEntry: ItemListNodeEntry { }) case let .group(_, _, strings, dateTimeFormat, nameDisplayOrder, peer, highlighted): var text: ItemListPeerItemText - if let cachedData = peer.peer.1 as? CachedChannelData, let memberCount = cachedData.participantsSummary.memberCount { + if let memberCount = peer.memberCount { text = .text("\(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string), \(memberCount > 0 ? strings.Conversation_StatusMembers(memberCount) : strings.PeopleNearby_NoMembers)", .secondary) } else { text = .text(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string, .secondary) } - return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: EnginePeer(peer.peer.0), aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, highlighted: highlighted, selectable: true, sectionId: self.section, action: { - arguments.openChat(peer.peer.0) + return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer.peer, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, highlighted: highlighted, selectable: true, sectionId: self.section, action: { + arguments.openChat(peer.peer) }, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: { node, gesture in - arguments.contextAction(peer.peer.0, node, gesture) + arguments.contextAction(peer.peer, node, gesture) }, hasTopGroupInset: false, tag: nil) case let .channelsHeader(_, text): return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section) case let .channel(_, _, strings, dateTimeFormat, nameDisplayOrder, peer, highlighted): var text: ItemListPeerItemText - if let cachedData = peer.peer.1 as? CachedChannelData, let memberCount = cachedData.participantsSummary.memberCount { + if let memberCount = peer.memberCount { text = .text("\(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string), \(strings.Conversation_StatusSubscribers(memberCount))", .secondary) } else { text = .text(strings.Map_DistanceAway(shortStringForDistance(strings: strings, distance: peer.distance)).string, .secondary) } - return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: EnginePeer(peer.peer.0), aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, highlighted: highlighted, selectable: true, sectionId: self.section, action: { - arguments.openChat(peer.peer.0) + return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, context: arguments.context, peer: peer.peer, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, highlighted: highlighted, selectable: true, sectionId: self.section, action: { + arguments.openChat(peer.peer) }, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, contextAction: { node, gesture in - arguments.contextAction(peer.peer.0, node, gesture) + arguments.contextAction(peer.peer, node, gesture) }, hasTopGroupInset: false, tag: nil) } } @@ -282,12 +282,12 @@ private struct PeersNearbyData: Equatable { let longitude: Double let address: String? let visible: Bool - let accountPeerId: PeerId + let accountPeerId: EnginePeer.Id let users: [PeerNearbyEntry] let groups: [PeerNearbyEntry] let channels: [PeerNearbyEntry] - init(latitude: Double, longitude: Double, address: String?, visible: Bool, accountPeerId: PeerId, users: [PeerNearbyEntry], groups: [PeerNearbyEntry], channels: [PeerNearbyEntry]) { + init(latitude: Double, longitude: Double, address: String?, visible: Bool, accountPeerId: EnginePeer.Id, users: [PeerNearbyEntry], groups: [PeerNearbyEntry], channels: [PeerNearbyEntry]) { self.latitude = latitude self.longitude = longitude self.address = address @@ -314,7 +314,7 @@ private func peersNearbyControllerEntries(data: PeersNearbyData?, state: PeersNe if let data = data, !data.users.isEmpty { var index: Int32 = 0 - var users = data.users.filter { $0.peer.0.id != data.accountPeerId } + var users = data.users.filter { $0.peer.id != data.accountPeerId } var effectiveExpanded = expanded if users.count > maxUsersDisplayedLimit && !expanded { users = Array(users.prefix(Int(maxUsersDisplayedLimit))) @@ -332,7 +332,7 @@ private func peersNearbyControllerEntries(data: PeersNearbyData?, state: PeersNe } } - var highlightedPeerId: PeerId? + var highlightedPeerId: EnginePeer.Id? if let chatLocation = chatLocation, case let .peer(peerId) = chatLocation { highlightedPeerId = peerId } @@ -342,7 +342,7 @@ private func peersNearbyControllerEntries(data: PeersNearbyData?, state: PeersNe if let data = data, !data.groups.isEmpty { var i: Int32 = 0 for group in data.groups { - entries.append(.group(i, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, group, highlightedPeerId == group.peer.0.id)) + entries.append(.group(i, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, group, highlightedPeerId == group.peer.id)) i += 1 } } @@ -350,7 +350,7 @@ private func peersNearbyControllerEntries(data: PeersNearbyData?, state: PeersNe if let data = data, !data.channels.isEmpty { var i: Int32 = 0 for channel in data.channels { - entries.append(.channel(i, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, channel, highlightedPeerId == channel.peer.0.id)) + entries.append(.channel(i, presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameDisplayOrder, channel, highlightedPeerId == channel.peer.id)) i += 1 } } @@ -386,7 +386,7 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent } } -private func peerNearbyContextMenuItems(context: AccountContext, peerId: PeerId, present: @escaping (ViewController) -> Void) -> Signal<[ContextMenuItem], NoError> { +private func peerNearbyContextMenuItems(context: AccountContext, peerId: EnginePeer.Id, present: @escaping (ViewController) -> Void) -> Signal<[ContextMenuItem], NoError> { return context.account.postbox.transaction { _ -> [ContextMenuItem] in let items: [ContextMenuItem] = [] @@ -409,8 +409,8 @@ public func peersNearbyController(context: AccountContext) -> ViewController { var replaceTopControllerImpl: ((ViewController) -> Void)? var presentControllerImpl: ((ViewController, ViewControllerPresentationArguments?) -> Void)? var presentInGlobalOverlayImpl: ((ViewController) -> Void)? - var navigateToProfileImpl: ((Peer, Int32) -> Void)? - var navigateToChatImpl: ((Peer) -> Void)? + var navigateToProfileImpl: ((EnginePeer, Int32) -> Void)? + var navigateToChatImpl: ((EnginePeer) -> Void)? let actionsDisposable = DisposableSet() let checkCreationAvailabilityDisposable = MetaDisposable() @@ -494,7 +494,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController { chatController.canReadHistory.set(false) let contextController = ContextController(account: context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: peerNearbyContextMenuItems(context: context, peerId: peer.id, present: { c in presentControllerImpl?(c, nil) - }) |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + }) |> map { ContextController.Items(items: $0) }, gesture: gesture) presentInGlobalOverlayImpl?(contextController) }, expandUsers: { expandedPromise.set(true) @@ -533,16 +533,16 @@ public func peersNearbyController(context: AccountContext) -> ViewController { case let .peer(id, expires, distance): if let peer = transaction.getPeer(id) { if id.namespace == Namespaces.Peer.CloudUser { - users.append(PeerNearbyEntry(peer: (peer, nil), expires: expires, distance: distance)) + users.append(PeerNearbyEntry(peer: EnginePeer(peer), memberCount: nil, expires: expires, distance: distance)) } else { let cachedData = transaction.getPeerCachedData(peerId: id) as? CachedChannelData - groups.append(PeerNearbyEntry(peer: (peer, cachedData), expires: expires, distance: distance)) + groups.append(PeerNearbyEntry(peer: EnginePeer(peer), memberCount: cachedData?.participantsSummary.memberCount, expires: expires, distance: distance)) } } case let .selfPeer(expires): visible = true if let peer = transaction.getPeer(context.account.peerId) { - users.append(PeerNearbyEntry(peer: (peer, nil), expires: expires, distance: 0)) + users.append(PeerNearbyEntry(peer: EnginePeer(peer), memberCount: nil, expires: expires, distance: 0)) } } } @@ -598,7 +598,7 @@ public func peersNearbyController(context: AccountContext) -> ViewController { controller?.clearItemNodesHighlight(animated: true) } navigateToProfileImpl = { [weak controller] peer, distance in - if let navigationController = controller?.navigationController as? NavigationController, let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .nearbyPeer(distance: distance), avatarInitiallyExpanded: peer.largeProfileImage != nil, fromChat: false) { + if let navigationController = controller?.navigationController as? NavigationController, let controller = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer._asPeer(), mode: .nearbyPeer(distance: distance), avatarInitiallyExpanded: peer.largeProfileImage != nil, fromChat: false) { navigationController.pushViewController(controller) } } diff --git a/submodules/ReactionSelectionNode/BUILD b/submodules/ReactionSelectionNode/BUILD deleted file mode 100644 index 9e1c9e099d..0000000000 --- a/submodules/ReactionSelectionNode/BUILD +++ /dev/null @@ -1,24 +0,0 @@ -load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") - -swift_library( - name = "ReactionSelectionNode", - module_name = "ReactionSelectionNode", - srcs = glob([ - "Sources/**/*.swift", - ]), - copts = [ - "-warnings-as-errors", - ], - deps = [ - "//submodules/Postbox:Postbox", - "//submodules/TelegramCore:TelegramCore", - "//submodules/AsyncDisplayKit:AsyncDisplayKit", - "//submodules/Display:Display", - "//submodules/AnimatedStickerNode:AnimatedStickerNode", - "//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode", - "//submodules/TelegramPresentationData:TelegramPresentationData", - ], - visibility = [ - "//visibility:public", - ], -) diff --git a/submodules/ReactionSelectionNode/Sources/ReactionAttachedNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionAttachedNode.swift deleted file mode 100644 index 3056366991..0000000000 --- a/submodules/ReactionSelectionNode/Sources/ReactionAttachedNode.swift +++ /dev/null @@ -1,323 +0,0 @@ -/*import Foundation -import AsyncDisplayKit -import AnimatedStickerNode -import Display -import Postbox -import TelegramCore -import TelegramPresentationData -import AppBundle - -private func generateBubbleImage(foreground: UIColor, diameter: CGFloat, shadowBlur: CGFloat) -> UIImage? { - return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(foreground.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - })?.stretchableImage(withLeftCapWidth: Int(diameter / 2.0 + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0)) -} - -private func generateBubbleShadowImage(shadow: UIColor, diameter: CGFloat, shadowBlur: CGFloat) -> UIImage? { - return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(UIColor.white.cgColor) - context.setShadow(offset: CGSize(), blur: shadowBlur, color: shadow.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.setShadow(offset: CGSize(), blur: 1.0, color: shadow.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.setFillColor(UIColor.clear.cgColor) - context.setBlendMode(.copy) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - })?.stretchableImage(withLeftCapWidth: Int(diameter / 2.0 + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0)) -} - -final class ReactionAttachedNode: ASDisplayNode { - private let account: Account - private let theme: PresentationTheme - private let reactions: [ReactionGestureItem] - - private let backgroundNode: ASImageNode - private let backgroundShadowNode: ASImageNode - private let bubbleNodes: [(ASImageNode, ASImageNode)] - private var reactionNodes: [ReactionNode] = [] - private var hasSelectedNode = false - - private let hapticFeedback = HapticFeedback() - - private var shadowBlur: CGFloat = 8.0 - private var minimizedReactionSize: CGFloat = 30.0 - private var maximizedReactionSize: CGFloat = 60.0 - private var smallCircleSize: CGFloat = 8.0 - - public init(account: Account, theme: PresentationTheme, reactions: [ReactionGestureItem]) { - self.account = account - self.theme = theme - self.reactions = reactions - - self.backgroundNode = ASImageNode() - self.backgroundNode.displaysAsynchronously = false - self.backgroundNode.displayWithoutProcessing = true - - self.backgroundShadowNode = ASImageNode() - self.backgroundShadowNode.displaysAsynchronously = false - self.backgroundShadowNode.displayWithoutProcessing = true - - self.bubbleNodes = (0 ..< 2).map { i -> (ASImageNode, ASImageNode) in - let imageNode = ASImageNode() - imageNode.displaysAsynchronously = false - imageNode.displayWithoutProcessing = true - - let shadowNode = ASImageNode() - shadowNode.displaysAsynchronously = false - shadowNode.displayWithoutProcessing = true - - return (imageNode, shadowNode) - } - - super.init() - - self.bubbleNodes.forEach { _, shadow in - self.addSubnode(shadow) - } - self.addSubnode(self.backgroundShadowNode) - self.bubbleNodes.forEach { foreground, _ in - self.addSubnode(foreground) - } - self.addSubnode(self.backgroundNode) - } - - func updateLayout(constrainedSize: CGSize, startingPoint: CGPoint, offsetFromStart: CGFloat, isInitial: Bool) { - let initialAnchorX = startingPoint.x - - if isInitial && self.reactionNodes.isEmpty { - let availableContentWidth = constrainedSize.width - var minimizedReactionSize = (availableContentWidth - self.maximizedReactionSize) / (CGFloat(self.reactions.count - 1) + CGFloat(self.reactions.count + 1) * 0.2) - minimizedReactionSize = max(16.0, floor(minimizedReactionSize)) - minimizedReactionSize = min(30.0, minimizedReactionSize) - - self.minimizedReactionSize = minimizedReactionSize - self.shadowBlur = floor(minimizedReactionSize * 0.26) - self.smallCircleSize = 8.0 - - let backgroundHeight = floor(minimizedReactionSize * 1.4) - - self.backgroundNode.image = generateBubbleImage(foreground: .white, diameter: backgroundHeight, shadowBlur: self.shadowBlur) - self.backgroundShadowNode.image = generateBubbleShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: backgroundHeight, shadowBlur: self.shadowBlur) - for i in 0 ..< self.bubbleNodes.count { - self.bubbleNodes[i].0.image = generateBubbleImage(foreground: .white, diameter: CGFloat(i + 1) * self.smallCircleSize, shadowBlur: self.shadowBlur) - self.bubbleNodes[i].1.image = generateBubbleShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: CGFloat(i + 1) * self.smallCircleSize, shadowBlur: self.shadowBlur) - } - - self.reactionNodes = self.reactions.map { reaction -> ReactionNode in - return ReactionNode(account: self.account, theme: self.theme, reaction: reaction, maximizedReactionSize: self.maximizedReactionSize, loadFirstFrame: true) - } - self.reactionNodes.forEach(self.addSubnode(_:)) - } - - let backgroundHeight: CGFloat = floor(self.minimizedReactionSize * 1.4) - - let reactionSpacing: CGFloat = floor(self.minimizedReactionSize * 0.2) - let minimizedReactionVerticalInset: CGFloat = floor((backgroundHeight - minimizedReactionSize) / 2.0) - - let contentWidth: CGFloat = CGFloat(self.reactionNodes.count - 1) * (minimizedReactionSize) + maximizedReactionSize + CGFloat(self.reactionNodes.count + 1) * reactionSpacing - - var backgroundFrame = CGRect(origin: CGPoint(x: -shadowBlur, y: -shadowBlur), size: CGSize(width: contentWidth + shadowBlur * 2.0, height: backgroundHeight + shadowBlur * 2.0)) - backgroundFrame = backgroundFrame.offsetBy(dx: initialAnchorX - contentWidth + backgroundHeight / 2.0, dy: startingPoint.y - backgroundHeight - 16.0) - backgroundFrame.origin.x = max(0.0, backgroundFrame.minX) - backgroundFrame.origin.x = min(constrainedSize.width - backgroundFrame.width, backgroundFrame.minX) - - self.backgroundNode.frame = backgroundFrame - self.backgroundShadowNode.frame = backgroundFrame - - let anchorMinX = backgroundFrame.minX + shadowBlur + backgroundHeight / 2.0 - let anchorMaxX = backgroundFrame.maxX - shadowBlur - backgroundHeight / 2.0 - let anchorX = max(anchorMinX, min(anchorMaxX, offsetFromStart)) - - var reactionX: CGFloat = backgroundFrame.minX + shadowBlur + reactionSpacing - if offsetFromStart > backgroundFrame.maxX - shadowBlur || offsetFromStart < backgroundFrame.minX { - self.hasSelectedNode = false - } else { - self.hasSelectedNode = true - } - - var maximizedIndex = Int(((anchorX - anchorMinX) / (anchorMaxX - anchorMinX)) * CGFloat(self.reactionNodes.count)) - maximizedIndex = max(0, min(self.reactionNodes.count - 1, maximizedIndex)) - - for iterationIndex in 0 ..< self.reactionNodes.count { - var i = iterationIndex - let isMaximized = i == maximizedIndex - - let reactionSize: CGFloat - if isMaximized { - reactionSize = maximizedReactionSize - } else { - reactionSize = minimizedReactionSize - } - - let transition: ContainedViewLayoutTransition - if isInitial { - transition = .immediate - } else { - transition = .animated(duration: 0.18, curve: .easeInOut) - } - - if self.reactionNodes[i].isMaximized != isMaximized { - self.reactionNodes[i].isMaximized = isMaximized - self.reactionNodes[i].updateIsAnimating(isMaximized, animated: !isInitial) - if isMaximized && !isInitial { - self.hapticFeedback.tap() - } - } - - var reactionFrame = CGRect(origin: CGPoint(x: reactionX, y: backgroundFrame.maxY - shadowBlur - minimizedReactionVerticalInset - reactionSize), size: CGSize(width: reactionSize, height: reactionSize)) - if isMaximized { - reactionFrame.origin.x -= 9.0 - reactionFrame.size.width += 18.0 - } - self.reactionNodes[i].updateLayout(size: reactionFrame.size, scale: reactionFrame.size.width / (maximizedReactionSize + 18.0), transition: transition, displayText: isMaximized) - - transition.updateFrame(node: self.reactionNodes[i], frame: reactionFrame, beginWithCurrentState: true) - - reactionX += reactionSize + reactionSpacing - } - - let mainBubbleFrame = CGRect(origin: CGPoint(x: anchorX - self.smallCircleSize - shadowBlur, y: backgroundFrame.maxY - shadowBlur - self.smallCircleSize - shadowBlur), size: CGSize(width: self.smallCircleSize * 2.0 + shadowBlur * 2.0, height: self.smallCircleSize * 2.0 + shadowBlur * 2.0)) - self.bubbleNodes[1].0.frame = mainBubbleFrame - self.bubbleNodes[1].1.frame = mainBubbleFrame - - let secondaryBubbleFrame = CGRect(origin: CGPoint(x: mainBubbleFrame.midX - 10.0 - (self.smallCircleSize + shadowBlur * 2.0) / 2.0, y: mainBubbleFrame.midY + 10.0 - (self.smallCircleSize + shadowBlur * 2.0) / 2.0), size: CGSize(width: self.smallCircleSize + shadowBlur * 2.0, height: self.smallCircleSize + shadowBlur * 2.0)) - self.bubbleNodes[0].0.frame = secondaryBubbleFrame - self.bubbleNodes[0].1.frame = secondaryBubbleFrame - } - - func animateIn() { - self.bubbleNodes[1].0.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - self.bubbleNodes[1].1.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - - self.bubbleNodes[0].0.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.05, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - self.bubbleNodes[0].1.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.05, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - - let backgroundOffset = CGPoint(x: -(self.backgroundNode.frame.width - shadowBlur) / 2.0 + 42.0, y: (self.backgroundNode.frame.height - shadowBlur) / 2.0) - let damping: CGFloat = 100.0 - - for i in 0 ..< self.reactionNodes.count { - let animationOffset: Double = 1.0 - Double(i) / Double(self.reactionNodes.count - 1) - var nodeOffset = CGPoint(x: self.reactionNodes[i].frame.minX - (self.backgroundNode.frame.minX + shadowBlur) / 2.0 - 42.0, y: self.reactionNodes[i].frame.minY - self.backgroundNode.frame.maxY - shadowBlur) - nodeOffset.x = -nodeOffset.x - nodeOffset.y = 30.0 - self.reactionNodes[i].layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5 + animationOffset * 0.28, initialVelocity: 0.0, damping: damping) - self.reactionNodes[i].layer.animateSpring(from: NSValue(cgPoint: nodeOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true) - } - - self.backgroundNode.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, damping: damping) - self.backgroundNode.layer.animateSpring(from: NSValue(cgPoint: backgroundOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true) - self.backgroundShadowNode.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, damping: damping) - self.backgroundShadowNode.layer.animateSpring(from: NSValue(cgPoint: backgroundOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true) - } - - func animateOut(into targetNode: ASImageNode?, hideTarget: Bool, completion: @escaping () -> Void) { - self.hapticFeedback.prepareTap() - - var completedContainer = false - var completedTarget = true - - let intermediateCompletion: () -> Void = { - if completedContainer && completedTarget { - completion() - } - } - - if let targetNode = targetNode { - for i in 0 ..< self.reactionNodes.count { - if let isMaximized = self.reactionNodes[i].isMaximized, isMaximized { - if let snapshotView = self.reactionNodes[i].view.snapshotContentTree() { - let targetSnapshotView = UIImageView() - targetSnapshotView.image = targetNode.image - targetSnapshotView.frame = self.view.convert(targetNode.bounds, from: targetNode.view) - self.reactionNodes[i].isHidden = true - self.view.addSubview(targetSnapshotView) - self.view.addSubview(snapshotView) - completedTarget = false - let targetPosition = self.view.convert(targetNode.bounds.center, from: targetNode.view) - let duration: Double = 0.3 - if hideTarget { - targetNode.isHidden = true - } - - snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false) - targetSnapshotView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - targetSnapshotView.layer.animateScale(from: snapshotView.bounds.width / targetSnapshotView.bounds.width, to: 0.5, duration: 0.3, removeOnCompletion: false) - - - let sourcePoint = snapshotView.center - let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y - 30.0) - - let x1 = sourcePoint.x - let y1 = sourcePoint.y - let x2 = midPoint.x - let y2 = midPoint.y - let x3 = targetPosition.x - let y3 = targetPosition.y - - let a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - let b = (x1 * x1 * (y2 - y3) + x3 * x3 * (y1 - y2) + x2 * x2 * (y3 - y1)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - let c = (x2 * x2 * (x3 * y1 - x1 * y3) + x2 * (x1 * x1 * y3 - x3 * x3 * y1) + x1 * x3 * (x3 - x1) * y2) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - - var keyframes: [AnyObject] = [] - for i in 0 ..< 10 { - let k = CGFloat(i) / CGFloat(10 - 1) - let x = sourcePoint.x * (1.0 - k) + targetPosition.x * k - let y = a * x * x + b * x + c - keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y))) - } - - snapshotView.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", removeOnCompletion: false, completion: { [weak self] _ in - if let strongSelf = self { - strongSelf.hapticFeedback.tap() - } - completedTarget = true - if hideTarget { - targetNode.isHidden = false - targetNode.layer.animateSpring(from: 0.5 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: duration, initialVelocity: 0.0, damping: 90.0) - } - intermediateCompletion() - }) - targetSnapshotView.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", removeOnCompletion: false) - - snapshotView.layer.animateScale(from: 1.0, to: (targetSnapshotView.bounds.width * 0.5) / snapshotView.bounds.width, duration: 0.3, removeOnCompletion: false) - } - break - } - } - } - - self.backgroundNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - self.backgroundShadowNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - self.backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - self.backgroundShadowNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in - completedContainer = true - intermediateCompletion() - }) - for (node, shadow) in self.bubbleNodes { - node.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - node.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - shadow.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - shadow.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - } - for i in 0 ..< self.reactionNodes.count { - self.reactionNodes[i].layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - self.reactionNodes[i].layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - } - } - - func selectedReaction() -> ReactionGestureItem? { - if !self.hasSelectedNode { - return nil - } - for i in 0 ..< self.reactionNodes.count { - if let isMaximized = self.reactionNodes[i].isMaximized, isMaximized { - return self.reactionNodes[i].reaction - } - } - return nil - } -} -*/ diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift deleted file mode 100644 index 1018936ef4..0000000000 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ /dev/null @@ -1,523 +0,0 @@ -import Foundation -import AsyncDisplayKit -import Display -import AnimatedStickerNode -import TelegramCore -import TelegramPresentationData - -public final class ReactionContextItem { - public enum Reaction { - case like - case unlike - } - - public let reaction: ReactionContextItem.Reaction - - public init(reaction: ReactionContextItem.Reaction) { - self.reaction = reaction - } -} - -private let largeCircleSize: CGFloat = 16.0 -private let smallCircleSize: CGFloat = 8.0 - -private func generateBackgroundImage(foreground: UIColor, diameter: CGFloat, shadowBlur: CGFloat) -> UIImage? { - return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(foreground.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - })?.stretchableImage(withLeftCapWidth: Int(shadowBlur + diameter / 2.0), topCapHeight: Int(shadowBlur + diameter / 2.0)) -} - -private func generateBackgroundShadowImage(shadow: UIColor, diameter: CGFloat, shadowBlur: CGFloat) -> UIImage? { - return generateImage(CGSize(width: diameter * 2.0 + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(shadow.cgColor) - context.setShadow(offset: CGSize(), blur: shadowBlur, color: shadow.cgColor) - - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur + diameter, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.fill(CGRect(origin: CGPoint(x: shadowBlur + diameter / 2.0, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - - context.setFillColor(UIColor.clear.cgColor) - context.setBlendMode(.copy) - - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur + diameter, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.fill(CGRect(origin: CGPoint(x: shadowBlur + diameter / 2.0, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - })?.stretchableImage(withLeftCapWidth: Int(diameter + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0)) -} - -private func generateBubbleImage(foreground: UIColor, diameter: CGFloat, shadowBlur: CGFloat) -> UIImage? { - return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(foreground.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - })?.stretchableImage(withLeftCapWidth: Int(diameter / 2.0 + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0)) -} - -private func generateBubbleShadowImage(shadow: UIColor, diameter: CGFloat, shadowBlur: CGFloat) -> UIImage? { - return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(shadow.cgColor) - context.setShadow(offset: CGSize(), blur: shadowBlur, color: shadow.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.setShadow(offset: CGSize(), blur: 1.0, color: shadow.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.setFillColor(UIColor.clear.cgColor) - context.setBlendMode(.copy) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - })?.stretchableImage(withLeftCapWidth: Int(diameter / 2.0 + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0)) -} - -public final class ReactionContextNode: ASDisplayNode { - private let theme: PresentationTheme - private let items: [ReactionContextItem] - - private let backgroundNode: ASImageNode - private let backgroundShadowNode: ASImageNode - private let backgroundContainerNode: ASDisplayNode - - private let largeCircleNode: ASImageNode - private let largeCircleShadowNode: ASImageNode - - private let smallCircleNode: ASImageNode - private let smallCircleShadowNode: ASImageNode - - private let contentContainer: ASDisplayNode - private var itemNodes: [ReactionNode] = [] - private let disclosureButton: HighlightTrackingButtonNode - - private var isExpanded: Bool = true - private var highlightedReaction: ReactionContextItem.Reaction? - private var validLayout: (CGSize, UIEdgeInsets, CGRect)? - - public var reactionSelected: ((ReactionGestureItem) -> Void)? - - private let hapticFeedback = HapticFeedback() - - public init(account: Account, theme: PresentationTheme, items: [ReactionContextItem]) { - self.theme = theme - self.items = items - - let shadowBlur: CGFloat = 5.0 - - self.backgroundNode = ASImageNode() - self.backgroundNode.displayWithoutProcessing = true - self.backgroundNode.displaysAsynchronously = false - - self.backgroundShadowNode = ASImageNode() - self.backgroundShadowNode.displayWithoutProcessing = true - self.backgroundShadowNode.displaysAsynchronously = false - - self.backgroundContainerNode = ASDisplayNode() - self.backgroundContainerNode.allowsGroupOpacity = true - - self.largeCircleNode = ASImageNode() - self.largeCircleNode.displayWithoutProcessing = true - self.largeCircleNode.displaysAsynchronously = false - - self.largeCircleShadowNode = ASImageNode() - self.largeCircleShadowNode.displayWithoutProcessing = true - self.largeCircleShadowNode.displaysAsynchronously = false - - self.smallCircleNode = ASImageNode() - self.smallCircleNode.displayWithoutProcessing = true - self.smallCircleNode.displaysAsynchronously = false - - self.smallCircleShadowNode = ASImageNode() - self.smallCircleShadowNode.displayWithoutProcessing = true - self.smallCircleShadowNode.displaysAsynchronously = false - - self.backgroundNode.image = generateBackgroundImage(foreground: theme.contextMenu.backgroundColor.withAlphaComponent(1.0), diameter: 52.0, shadowBlur: shadowBlur) - - self.backgroundShadowNode.image = generateBackgroundShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: 52.0, shadowBlur: shadowBlur) - - self.largeCircleNode.image = generateBubbleImage(foreground: theme.contextMenu.backgroundColor.withAlphaComponent(1.0), diameter: largeCircleSize, shadowBlur: shadowBlur) - self.smallCircleNode.image = generateBubbleImage(foreground: theme.contextMenu.backgroundColor.withAlphaComponent(1.0), diameter: smallCircleSize, shadowBlur: shadowBlur) - - self.largeCircleShadowNode.image = generateBubbleShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: largeCircleSize, shadowBlur: shadowBlur) - self.smallCircleShadowNode.image = generateBubbleShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: smallCircleSize, shadowBlur: shadowBlur) - - self.contentContainer = ASDisplayNode() - self.contentContainer.clipsToBounds = true - - self.disclosureButton = HighlightTrackingButtonNode() - self.disclosureButton.hitTestSlop = UIEdgeInsets(top: -6.0, left: -6.0, bottom: -6.0, right: -6.0) - let buttonImage = generateImage(CGSize(width: 30.0, height: 30.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(theme.contextMenu.dimColor.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(), size: size)) - context.setBlendMode(.copy) - context.setStrokeColor(UIColor.clear.cgColor) - context.setLineWidth(2.0) - context.setLineCap(.round) - context.setLineJoin(.round) - context.beginPath() - context.move(to: CGPoint(x: 8.0, y: size.height / 2.0 + 3.0)) - context.addLine(to: CGPoint(x: size.width / 2.0, y: 11.0)) - context.addLine(to: CGPoint(x: size.width - 8.0, y: size.height / 2.0 + 3.0)) - context.strokePath() - }) - self.disclosureButton.setImage(buttonImage, for: []) - - super.init() - - self.addSubnode(self.smallCircleShadowNode) - self.addSubnode(self.largeCircleShadowNode) - self.addSubnode(self.backgroundShadowNode) - - self.backgroundContainerNode.addSubnode(self.smallCircleNode) - self.backgroundContainerNode.addSubnode(self.largeCircleNode) - self.backgroundContainerNode.addSubnode(self.backgroundNode) - self.addSubnode(self.backgroundContainerNode) - - self.contentContainer.addSubnode(self.disclosureButton) - - self.itemNodes = self.items.map { item in - let reactionItem: ReactionGestureItem - switch item.reaction { - case .like: - reactionItem = .like - case .unlike: - reactionItem = .unlike - } - return ReactionNode(account: account, theme: theme, reaction: reactionItem, maximizedReactionSize: 30.0, loadFirstFrame: true) - } - self.itemNodes.forEach(self.contentContainer.addSubnode) - - self.addSubnode(self.contentContainer) - - self.disclosureButton.addTarget(self, action: #selector(self.disclosurePressed), forControlEvents: .touchUpInside) - self.disclosureButton.highligthedChanged = { [weak self] highlighted in - if highlighted { - self?.disclosureButton.layer.animateScale(from: 1.0, to: 0.8, duration: 0.15, removeOnCompletion: false) - } else { - self?.disclosureButton.layer.animateScale(from: 0.8, to: 1.0, duration: 0.25) - } - } - } - - override public func didLoad() { - super.didLoad() - - self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) - } - - public func updateLayout(size: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, transition: ContainedViewLayoutTransition) { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: transition, animateInFromAnchorRect: nil, animateOutToAnchorRect: nil) - } - - private func calculateBackgroundFrame(containerSize: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, contentSize: CGSize) -> (CGRect, Bool) { - var contentSize = contentSize - contentSize.width = max(52.0, contentSize.width) - contentSize.height = 52.0 - - let sideInset: CGFloat = 12.0 - let backgroundOffset: CGPoint = CGPoint(x: 22.0, y: -7.0) - - var rect: CGRect - let isLeftAligned: Bool - if anchorRect.maxX < containerSize.width - backgroundOffset.x - sideInset { - rect = CGRect(origin: CGPoint(x: anchorRect.maxX - contentSize.width + backgroundOffset.x, y: anchorRect.minY - contentSize.height + backgroundOffset.y), size: contentSize) - isLeftAligned = true - } else { - rect = CGRect(origin: CGPoint(x: anchorRect.minX - backgroundOffset.x - 4.0, y: anchorRect.minY - contentSize.height + backgroundOffset.y), size: contentSize) - isLeftAligned = false - } - rect.origin.x = max(sideInset, rect.origin.x) - rect.origin.y = max(insets.top + sideInset, rect.origin.y) - rect.origin.x = min(containerSize.width - contentSize.width - sideInset, rect.origin.x) - return (rect, isLeftAligned) - } - - private func updateLayout(size: CGSize, insets: UIEdgeInsets, anchorRect: CGRect, transition: ContainedViewLayoutTransition, animateInFromAnchorRect: CGRect?, animateOutToAnchorRect: CGRect?, animateReactionHighlight: Bool = false) { - self.validLayout = (size, insets, anchorRect) - - let sideInset: CGFloat = 12.0 - let itemSpacing: CGFloat = 6.0 - let minimizedItemSize: CGFloat = 30.0 - let maximizedItemSize: CGFloat = 30.0 - 18.0 - let shadowBlur: CGFloat = 5.0 - let verticalInset: CGFloat = 13.0 - let rowHeight: CGFloat = 30.0 - let rowSpacing: CGFloat = itemSpacing - - let columnCount = min(6, self.items.count) - let contentWidth = CGFloat(columnCount) * minimizedItemSize + (CGFloat(columnCount) - 1.0) * itemSpacing + sideInset * 2.0 - let rowCount = self.items.count / columnCount + (self.items.count % columnCount == 0 ? 0 : 1) - - let expandedRowCount = self.isExpanded ? rowCount : 1 - - let contentHeight = verticalInset * 2.0 + rowHeight * CGFloat(expandedRowCount) + CGFloat(expandedRowCount - 1) * rowSpacing - - let (backgroundFrame, isLeftAligned) = self.calculateBackgroundFrame(containerSize: size, insets: insets, anchorRect: anchorRect, contentSize: CGSize(width: contentWidth, height: contentHeight)) - - transition.updateFrame(node: self.contentContainer, frame: backgroundFrame) - - for i in 0 ..< self.items.count { - let rowIndex = i / columnCount - let columnIndex = i % columnCount - let row = CGFloat(rowIndex) - let column = CGFloat(columnIndex) - - let itemSize: CGFloat = minimizedItemSize - let itemOffset: CGFloat = 0.0 - - let itemFrame = CGRect(origin: CGPoint(x: sideInset + column * (minimizedItemSize + itemSpacing) - itemOffset, y: verticalInset + row * (rowHeight + rowSpacing) + floor((rowHeight - minimizedItemSize) / 2.0) - itemOffset), size: CGSize(width: itemSize, height: itemSize)) - transition.updateFrame(node: self.itemNodes[i], frame: itemFrame, beginWithCurrentState: true) - self.itemNodes[i].updateLayout(size: CGSize(width: itemSize, height: itemSize), scale: itemSize / (maximizedItemSize + 18.0), transition: transition, displayText: false) - self.itemNodes[i].updateIsAnimating(false, animated: false) - if rowIndex != 0 || columnIndex == columnCount - 1 { - if self.isExpanded { - if self.itemNodes[i].alpha.isZero { - self.itemNodes[i].alpha = 1.0 - if transition.isAnimated { - let delayOffset: Double = 1.0 - Double(columnIndex) / Double(columnCount - 1) - self.itemNodes[i].layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4 + delayOffset * 0.32, initialVelocity: 0.0, damping: 95.0) - self.itemNodes[i].layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.05) - } - } - } else { - self.itemNodes[i].alpha = 0.0 - } - } else { - self.itemNodes[i].alpha = 1.0 - } - - if rowIndex == 0 && columnIndex == columnCount - 1 { - transition.updateFrame(node: self.disclosureButton, frame: itemFrame) - if self.isExpanded { - if self.disclosureButton.alpha.isEqual(to: 1.0) { - self.disclosureButton.alpha = 0.0 - if transition.isAnimated { - self.disclosureButton.layer.animateScale(from: 0.8, to: 0.1, duration: 0.2, removeOnCompletion: false) - self.disclosureButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak self] _ in - self?.disclosureButton.layer.removeAnimation(forKey: "scale") - }) - } - } - } else { - self.disclosureButton.alpha = 1.0 - } - } - } - - let isInOverflow = backgroundFrame.maxY > anchorRect.minY - let backgroundAlpha: CGFloat = isInOverflow ? 1.0 : 0.8 - let shadowAlpha: CGFloat = isInOverflow ? 1.0 : 0.0 - transition.updateAlpha(node: self.backgroundContainerNode, alpha: backgroundAlpha) - transition.updateAlpha(node: self.backgroundShadowNode, alpha: shadowAlpha) - transition.updateAlpha(node: self.largeCircleShadowNode, alpha: shadowAlpha) - transition.updateAlpha(node: self.smallCircleShadowNode, alpha: shadowAlpha) - - transition.updateFrame(node: self.backgroundContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width, height: size.height))) - - transition.updateFrame(node: self.backgroundNode, frame: backgroundFrame.insetBy(dx: -shadowBlur, dy: -shadowBlur)) - transition.updateFrame(node: self.backgroundShadowNode, frame: backgroundFrame.insetBy(dx: -shadowBlur, dy: -shadowBlur)) - - let largeCircleFrame: CGRect - let smallCircleFrame: CGRect - if isLeftAligned { - largeCircleFrame = CGRect(origin: CGPoint(x: backgroundFrame.midX - floor(largeCircleSize / 2.0), y: backgroundFrame.maxY - largeCircleSize / 2.0), size: CGSize(width: largeCircleSize, height: largeCircleSize)) - smallCircleFrame = CGRect(origin: CGPoint(x: largeCircleFrame.maxX - 3.0, y: largeCircleFrame.maxY + 2.0), size: CGSize(width: smallCircleSize, height: smallCircleSize)) - } else { - largeCircleFrame = CGRect(origin: CGPoint(x: backgroundFrame.midX - floor(largeCircleSize / 2.0), y: backgroundFrame.maxY - largeCircleSize / 2.0), size: CGSize(width: largeCircleSize, height: largeCircleSize)) - smallCircleFrame = CGRect(origin: CGPoint(x: largeCircleFrame.minX + 3.0 - smallCircleSize, y: largeCircleFrame.maxY + 2.0), size: CGSize(width: smallCircleSize, height: smallCircleSize)) - } - - transition.updateFrame(node: self.largeCircleNode, frame: largeCircleFrame.insetBy(dx: -shadowBlur, dy: -shadowBlur)) - transition.updateFrame(node: self.largeCircleShadowNode, frame: largeCircleFrame.insetBy(dx: -shadowBlur, dy: -shadowBlur)) - transition.updateFrame(node: self.smallCircleNode, frame: smallCircleFrame.insetBy(dx: -shadowBlur, dy: -shadowBlur)) - transition.updateFrame(node: self.smallCircleShadowNode, frame: smallCircleFrame.insetBy(dx: -shadowBlur, dy: -shadowBlur)) - - if let animateInFromAnchorRect = animateInFromAnchorRect { - let springDuration: Double = 0.42 - let springDamping: CGFloat = 104.0 - - let sourceBackgroundFrame = self.calculateBackgroundFrame(containerSize: size, insets: insets, anchorRect: animateInFromAnchorRect, contentSize: CGSize(width: contentWidth, height: contentHeight)).0 - - self.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: sourceBackgroundFrame.minX - backgroundFrame.minX, y: sourceBackgroundFrame.minY - backgroundFrame.minY)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true) - } else if let animateOutToAnchorRect = animateOutToAnchorRect { - let targetBackgroundFrame = self.calculateBackgroundFrame(containerSize: size, insets: insets, anchorRect: animateOutToAnchorRect, contentSize: CGSize(width: contentWidth, height: contentHeight)).0 - - self.layer.animatePosition(from: CGPoint(), to: CGPoint(x: targetBackgroundFrame.minX - backgroundFrame.minX, y: targetBackgroundFrame.minY - backgroundFrame.minY), duration: 0.2, removeOnCompletion: false, additive: true) - } - } - - public func animateIn(from sourceAnchorRect: CGRect) { - self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) - - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: .immediate, animateInFromAnchorRect: sourceAnchorRect, animateOutToAnchorRect: nil) - } - - let smallCircleDuration: Double = 0.5 - let largeCircleDuration: Double = 0.5 - let largeCircleDelay: Double = 0.08 - let mainCircleDuration: Double = 0.5 - let mainCircleDelay: Double = 0.1 - - self.smallCircleNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: smallCircleDuration) - self.smallCircleShadowNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: smallCircleDuration) - - self.largeCircleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: largeCircleDelay) - self.largeCircleNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: largeCircleDuration, delay: largeCircleDelay) - self.largeCircleShadowNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: largeCircleDuration, delay: largeCircleDelay) - - self.backgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: mainCircleDelay) - self.backgroundNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: mainCircleDuration, delay: mainCircleDelay) - self.backgroundShadowNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: mainCircleDuration, delay: mainCircleDelay) - - if let itemNode = self.itemNodes.first { - itemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: mainCircleDelay) - itemNode.didAppear() - itemNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: mainCircleDuration, delay: mainCircleDelay, completion: { _ in - }) - } - } - - public func animateOut(to targetAnchorRect: CGRect?, animatingOutToReaction: Bool) { - self.backgroundNode.layer.animateAlpha(from: self.backgroundNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) - self.backgroundShadowNode.layer.animateAlpha(from: self.backgroundShadowNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) - self.largeCircleNode.layer.animateAlpha(from: self.largeCircleNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) - self.largeCircleShadowNode.layer.animateAlpha(from: self.largeCircleShadowNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) - self.smallCircleNode.layer.animateAlpha(from: self.smallCircleNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) - self.smallCircleShadowNode.layer.animateAlpha(from: self.smallCircleShadowNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) - for itemNode in self.itemNodes { - itemNode.layer.animateAlpha(from: itemNode.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) - } - self.disclosureButton.layer.animateAlpha(from: self.disclosureButton.alpha, to: 0.0, duration: 0.2, removeOnCompletion: false) - - if let targetAnchorRect = targetAnchorRect, let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: .immediate, animateInFromAnchorRect: nil, animateOutToAnchorRect: targetAnchorRect) - } - } - - public func animateOutToReaction(value: String, targetEmptyNode: ASDisplayNode, targetFilledNode: ASDisplayNode, hideNode: Bool, completion: @escaping () -> Void) { - for itemNode in self.itemNodes { - switch itemNode.reaction { - case .like: - if let snapshotView = itemNode.view.snapshotContentTree(keepTransform: true), let targetSnapshotView = targetFilledNode.view.snapshotContentTree() { - targetSnapshotView.frame = self.view.convert(targetFilledNode.bounds, from: targetFilledNode.view) - itemNode.isHidden = true - self.view.addSubview(targetSnapshotView) - self.view.addSubview(snapshotView) - snapshotView.frame = itemNode.view.convert(itemNode.view.bounds, to: self.view) - - var completedTarget = false - let intermediateCompletion: () -> Void = { - if completedTarget { - completion() - } - } - - let targetPosition = self.view.convert(targetFilledNode.bounds.center, from: targetFilledNode.view) - let duration: Double = 0.3 - if hideNode { - targetFilledNode.isHidden = true - } - - snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false) - targetSnapshotView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - targetSnapshotView.layer.animateScale(from: snapshotView.bounds.width / targetSnapshotView.bounds.width, to: 0.5, duration: 0.3, removeOnCompletion: false) - - let sourcePoint = snapshotView.center - let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y - 30.0) - - let x1 = sourcePoint.x - let y1 = sourcePoint.y - let x2 = midPoint.x - let y2 = midPoint.y - let x3 = targetPosition.x - let y3 = targetPosition.y - - let a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - let b = (x1 * x1 * (y2 - y3) + x3 * x3 * (y1 - y2) + x2 * x2 * (y3 - y1)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - let c = (x2 * x2 * (x3 * y1 - x1 * y3) + x2 * (x1 * x1 * y3 - x3 * x3 * y1) + x1 * x3 * (x3 - x1) * y2) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - - var keyframes: [AnyObject] = [] - for i in 0 ..< 10 { - let k = CGFloat(i) / CGFloat(10 - 1) - let x = sourcePoint.x * (1.0 - k) + targetPosition.x * k - let y = a * x * x + b * x + c - keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y))) - } - - snapshotView.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", removeOnCompletion: false, completion: { [weak self] _ in - if let strongSelf = self { - strongSelf.hapticFeedback.tap() - } - completedTarget = true - if hideNode { - targetFilledNode.isHidden = false - targetFilledNode.layer.animateSpring(from: 0.5 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: duration, initialVelocity: 0.0, damping: 90.0) - targetEmptyNode.layer.animateSpring(from: 0.5 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: duration, initialVelocity: 0.0, damping: 90.0) - } - intermediateCompletion() - }) - targetSnapshotView.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", removeOnCompletion: false) - - snapshotView.layer.animateScale(from: 1.0, to: (targetSnapshotView.bounds.width * 0.5) / snapshotView.bounds.width, duration: 0.3, removeOnCompletion: false) - return - } - default: - break - } - } - completion() - } - - override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - let contentPoint = self.contentContainer.view.convert(point, from: self.view) - if !self.disclosureButton.alpha.isZero { - if let result = self.disclosureButton.hitTest(self.disclosureButton.view.convert(point, from: self.view), with: event) { - return result - } - } - for itemNode in self.itemNodes { - if !itemNode.alpha.isZero && itemNode.frame.contains(contentPoint) { - return self.view - } - } - return nil - } - - @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { - if case .ended = recognizer.state { - let point = recognizer.location(in: self.view) - if let reaction = self.reaction(at: point) { - self.reactionSelected?(reaction) - } - } - } - - public func reaction(at point: CGPoint) -> ReactionGestureItem? { - let contentPoint = self.contentContainer.view.convert(point, from: self.view) - for itemNode in self.itemNodes { - if !itemNode.alpha.isZero && itemNode.frame.contains(contentPoint) { - return itemNode.reaction - } - } - for itemNode in self.itemNodes { - if !itemNode.alpha.isZero && itemNode.frame.insetBy(dx: -8.0, dy: -8.0).contains(contentPoint) { - return itemNode.reaction - } - } - return nil - } - - public func setHighlightedReaction(_ value: ReactionContextItem.Reaction?) { - self.highlightedReaction = value - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: .animated(duration: 0.18, curve: .easeInOut), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) - } - } - - @objc private func disclosurePressed() { - self.isExpanded = true - if let (size, insets, anchorRect) = self.validLayout { - self.updateLayout(size: size, insets: insets, anchorRect: anchorRect, transition: .animated(duration: 0.3, curve: .spring), animateInFromAnchorRect: nil, animateOutToAnchorRect: nil, animateReactionHighlight: true) - } - } -} diff --git a/submodules/ReactionSelectionNode/Sources/ReactionGestureItem.swift b/submodules/ReactionSelectionNode/Sources/ReactionGestureItem.swift deleted file mode 100644 index e1adfa2fe8..0000000000 --- a/submodules/ReactionSelectionNode/Sources/ReactionGestureItem.swift +++ /dev/null @@ -1,8 +0,0 @@ -import Foundation -import Postbox -import TelegramCore - -public enum ReactionGestureItem { - case like - case unlike -} diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift deleted file mode 100644 index b6f695e21c..0000000000 --- a/submodules/ReactionSelectionNode/Sources/ReactionSelectionNode.swift +++ /dev/null @@ -1,487 +0,0 @@ -import Foundation -import AsyncDisplayKit -import Display -import Postbox -import TelegramCore -import TelegramPresentationData -import AppBundle -import AnimatedStickerNode -import TelegramAnimatedStickerNode - -private func generateBubbleImage(foreground: UIColor, diameter: CGFloat, shadowBlur: CGFloat) -> UIImage? { - return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(foreground.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - })?.stretchableImage(withLeftCapWidth: Int(diameter / 2.0 + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0)) -} - -private func generateBubbleShadowImage(shadow: UIColor, diameter: CGFloat, shadowBlur: CGFloat) -> UIImage? { - return generateImage(CGSize(width: diameter + shadowBlur * 2.0, height: diameter + shadowBlur * 2.0), rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - context.setFillColor(UIColor.white.cgColor) - context.setShadow(offset: CGSize(), blur: shadowBlur, color: shadow.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.setShadow(offset: CGSize(), blur: 1.0, color: shadow.cgColor) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - context.setFillColor(UIColor.clear.cgColor) - context.setBlendMode(.copy) - context.fillEllipse(in: CGRect(origin: CGPoint(x: shadowBlur, y: shadowBlur), size: CGSize(width: diameter, height: diameter))) - })?.stretchableImage(withLeftCapWidth: Int(diameter / 2.0 + shadowBlur / 2.0), topCapHeight: Int(diameter / 2.0 + shadowBlur / 2.0)) -} - -private let font = Font.medium(13.0) - -final class ReactionNode: ASDisplayNode { - let reaction: ReactionGestureItem - private let textBackgroundNode: ASImageNode - private let textNode: ImmediateTextNode - private let animationNode: AnimatedStickerNode - private let imageNode: ASImageNode - private let additionalImageNode: ASImageNode - var isMaximized: Bool? - private let intrinsicSize: CGSize - private let intrinsicOffset: CGPoint - - init(account: Account, theme: PresentationTheme, reaction: ReactionGestureItem, maximizedReactionSize: CGFloat, loadFirstFrame: Bool) { - self.reaction = reaction - - self.textBackgroundNode = ASImageNode() - self.textBackgroundNode.displaysAsynchronously = false - self.textBackgroundNode.displayWithoutProcessing = true - self.textBackgroundNode.image = generateStretchableFilledCircleImage(diameter: 20.0, color: theme.chat.serviceMessage.components.withDefaultWallpaper.dateFillFloating.withAlphaComponent(0.8)) - self.textBackgroundNode.alpha = 0.0 - - self.textNode = ImmediateTextNode() - self.textNode.displaysAsynchronously = false - self.textNode.isUserInteractionEnabled = false - - let reactionText: String = "" - - self.textNode.attributedText = NSAttributedString(string: reactionText, font: font, textColor: theme.chat.serviceMessage.dateTextColor.withWallpaper) - let textSize = self.textNode.updateLayout(CGSize(width: 200.0, height: 100.0)) - let textBackgroundSize = CGSize(width: textSize.width + 12.0, height: 20.0) - let textBackgroundFrame = CGRect(origin: CGPoint(), size: textBackgroundSize) - let textFrame = CGRect(origin: CGPoint(x: floor((textBackgroundFrame.width - textSize.width) / 2.0), y: floor((textBackgroundFrame.height - textSize.height) / 2.0)), size: textSize) - self.textBackgroundNode.frame = textBackgroundFrame - self.textNode.frame = textFrame - self.textNode.alpha = 0.0 - - self.animationNode = AnimatedStickerNode() - self.animationNode.automaticallyLoadFirstFrame = loadFirstFrame - self.animationNode.playToCompletionOnStop = true - - var intrinsicSize = CGSize(width: maximizedReactionSize + 14.0, height: maximizedReactionSize + 14.0) - - self.imageNode = ASImageNode() - self.additionalImageNode = ASImageNode() - switch reaction { - case .like: - self.intrinsicOffset = CGPoint(x: 0.0, y: 0.0) - self.imageNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Reactions/ContextHeartFilled"), color: UIColor(rgb: 0xfe1512)) - case .unlike: - self.intrinsicOffset = CGPoint(x: 0.0, y: 0.0) - self.imageNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Reactions/ContextHeartBrokenL"), color: UIColor(rgb: 0xfe1512)) - self.additionalImageNode.image = generateTintedImage(image: UIImage(bundleImageName: "Chat/Reactions/ContextHeartBrokenR"), color: UIColor(rgb: 0xfe1512)) - } - - if let image = self.imageNode.image { - intrinsicSize = image.size - } - - self.intrinsicSize = intrinsicSize - - super.init() - - //self.backgroundColor = .gray - - //self.textBackgroundNode.addSubnode(self.textNode) - //self.addSubnode(self.textBackgroundNode) - - //self.addSubnode(self.animationNode) - self.addSubnode(self.imageNode) - self.addSubnode(self.additionalImageNode) - self.animationNode.updateLayout(size: self.intrinsicSize) - self.animationNode.frame = CGRect(origin: CGPoint(), size: self.intrinsicSize) - - switch reaction { - case .like: - self.imageNode.frame = CGRect(origin: CGPoint(x: -5.0, y: -5.0), size: self.intrinsicSize) - case .unlike: - self.imageNode.frame = CGRect(origin: CGPoint(x: -6.0, y: -5.0), size: self.intrinsicSize) - self.additionalImageNode.frame = CGRect(origin: CGPoint(x: -3.0, y: -5.0), size: self.intrinsicSize) - } - } - - func updateLayout(size: CGSize, scale: CGFloat, transition: ContainedViewLayoutTransition, displayText: Bool) { - /*transition.updatePosition(node: self.animationNode, position: CGPoint(x: size.width / 2.0 + self.intrinsicOffset.x * scale, y: size.height / 2.0 + self.intrinsicOffset.y * scale), beginWithCurrentState: true) - transition.updateTransformScale(node: self.animationNode, scale: scale, beginWithCurrentState: true) - transition.updatePosition(node: self.imageNode, position: CGPoint(x: size.width / 2.0 + self.intrinsicOffset.x * scale, y: size.height / 2.0 + self.intrinsicOffset.y * scale), beginWithCurrentState: true) - transition.updateTransformScale(node: self.imageNode, scale: scale, beginWithCurrentState: true) - - transition.updatePosition(node: self.textBackgroundNode, position: CGPoint(x: size.width / 2.0, y: displayText ? -24.0 : (size.height / 2.0)), beginWithCurrentState: true) - transition.updateTransformScale(node: self.textBackgroundNode, scale: displayText ? 1.0 : 0.1, beginWithCurrentState: true) - - transition.updateAlpha(node: self.textBackgroundNode, alpha: displayText ? 1.0 : 0.0, beginWithCurrentState: true) - transition.updateAlpha(node: self.textNode, alpha: displayText ? 1.0 : 0.0, beginWithCurrentState: true)*/ - } - - func updateIsAnimating(_ isAnimating: Bool, animated: Bool) { - if isAnimating { - self.animationNode.visibility = true - } else { - self.animationNode.visibility = false - } - } - - func didAppear() { - switch self.reaction { - case .like: - self.imageNode.layer.animateScale(from: 1.0, to: 1.08, duration: 0.12, delay: 0.22, removeOnCompletion: false, completion: { [weak self] _ in - guard let strongSelf = self else { - return - } - strongSelf.imageNode.layer.animateScale(from: 1.08, to: 1.0, duration: 0.12) - }) - case .unlike: - self.imageNode.layer.animatePosition(from: CGPoint(x: -2.5, y: 0.0), to: CGPoint(), duration: 0.2, delay: 0.15, additive: true) - self.additionalImageNode.layer.animatePosition(from: CGPoint(x: 2.5, y: 0.0), to: CGPoint(), duration: 0.2, delay: 0.15, additive: true) - } - } -} - -final class ReactionSelectionNode: ASDisplayNode { - private let account: Account - private let theme: PresentationTheme - private let reactions: [ReactionGestureItem] - - private let backgroundNode: ASImageNode - private let backgroundShadowNode: ASImageNode - private let bubbleNodes: [(ASImageNode, ASImageNode)] - private var reactionNodes: [ReactionNode] = [] - private var hasSelectedNode = false - - private let hapticFeedback = HapticFeedback() - - private var shadowBlur: CGFloat = 8.0 - private var minimizedReactionSize: CGFloat = 28.0 - private var smallCircleSize: CGFloat = 14.0 - - private var isRightAligned: Bool = false - - public init(account: Account, theme: PresentationTheme, reactions: [ReactionGestureItem]) { - self.account = account - self.theme = theme - self.reactions = reactions - - self.backgroundNode = ASImageNode() - self.backgroundNode.displaysAsynchronously = false - self.backgroundNode.displayWithoutProcessing = true - - self.backgroundShadowNode = ASImageNode() - self.backgroundShadowNode.displaysAsynchronously = false - self.backgroundShadowNode.displayWithoutProcessing = true - - self.bubbleNodes = (0 ..< 2).map { i -> (ASImageNode, ASImageNode) in - let imageNode = ASImageNode() - imageNode.displaysAsynchronously = false - imageNode.displayWithoutProcessing = true - - let shadowNode = ASImageNode() - shadowNode.displaysAsynchronously = false - shadowNode.displayWithoutProcessing = true - - return (imageNode, shadowNode) - } - - super.init() - - self.bubbleNodes.forEach { _, shadow in - //self.addSubnode(shadow) - } - self.addSubnode(self.backgroundShadowNode) - self.bubbleNodes.forEach { foreground, _ in - //self.addSubnode(foreground) - } - self.addSubnode(self.backgroundNode) - } - - func updateLayout(constrainedSize: CGSize, startingPoint: CGPoint, offsetFromStart: CGFloat, isInitial: Bool, touchPoint: CGPoint) { - let initialAnchorX = startingPoint.x - - var isRightAligned = false - if initialAnchorX > constrainedSize.width / 2.0 { - isRightAligned = true - } - - let reactionSideInset: CGFloat = 10.0 - let reactionSpacing: CGFloat = 6.0 - let minReactionSpacing: CGFloat = 2.0 - let minimizedReactionSize = self.minimizedReactionSize - let contentWidth: CGFloat = CGFloat(self.reactions.count) * (minimizedReactionSize) + CGFloat(self.reactions.count - 1) * reactionSpacing + reactionSideInset * 2.0 - let spaceForMaximizedReaction = CGFloat(self.reactions.count - 1) * reactionSpacing - CGFloat(self.reactions.count - 1) * minReactionSpacing - let maximizedReactionSize: CGFloat = minimizedReactionSize + spaceForMaximizedReaction - let backgroundHeight: CGFloat = floor(self.minimizedReactionSize * 1.8) - - var backgroundFrame = CGRect(origin: CGPoint(x: -shadowBlur, y: -shadowBlur), size: CGSize(width: contentWidth + shadowBlur * 2.0, height: backgroundHeight + shadowBlur * 2.0)) - if constrainedSize.width > 500.0 { - backgroundFrame = backgroundFrame.offsetBy(dx: constrainedSize.width - contentWidth - 44.0, dy: startingPoint.y - backgroundHeight - 12.0) - } else { - backgroundFrame = backgroundFrame.offsetBy(dx: floor((constrainedSize.width - contentWidth) / 2.0), dy: startingPoint.y - backgroundHeight - 12.0) - } - backgroundFrame.origin.x = max(0.0, backgroundFrame.minX) - backgroundFrame.origin.x = min(constrainedSize.width - backgroundFrame.width, backgroundFrame.minX) - - let anchorMinX = backgroundFrame.minX + shadowBlur + backgroundHeight / 2.0 - let anchorMaxX = backgroundFrame.maxX - shadowBlur - backgroundHeight / 2.0 - let anchorX = max(anchorMinX, min(anchorMaxX, offsetFromStart)) - - var maximizedIndex = -1 - /*if let reaction = self.reactions.last, case .reply = reaction { - maximizedIndex = self.reactions.count - 1 - }*/ - if backgroundFrame.insetBy(dx: -10.0, dy: -10.0).offsetBy(dx: 0.0, dy: 10.0).contains(touchPoint) { - maximizedIndex = Int(((touchPoint.x - anchorMinX) / (anchorMaxX - anchorMinX)) * CGFloat(self.reactionNodes.count)) - maximizedIndex = max(0, min(self.reactionNodes.count - 1, maximizedIndex)) - } - - let interReactionSpacing: CGFloat - if maximizedIndex != -1 { - interReactionSpacing = minReactionSpacing - } else { - interReactionSpacing = reactionSpacing - } - - if isInitial && self.reactionNodes.isEmpty { - self.shadowBlur = floor(minimizedReactionSize * 0.26) - self.smallCircleSize = 14.0 - - self.backgroundNode.image = generateBubbleImage(foreground: .white, diameter: backgroundHeight, shadowBlur: self.shadowBlur) - self.backgroundShadowNode.image = generateBubbleShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: backgroundHeight, shadowBlur: self.shadowBlur) - for i in 0 ..< self.bubbleNodes.count { - self.bubbleNodes[i].0.image = generateBubbleImage(foreground: .white, diameter: CGFloat(i + 1) * self.smallCircleSize, shadowBlur: self.shadowBlur) - self.bubbleNodes[i].1.image = generateBubbleShadowImage(shadow: UIColor(white: 0.0, alpha: 0.2), diameter: CGFloat(i + 1) * self.smallCircleSize, shadowBlur: self.shadowBlur) - } - - self.reactionNodes = self.reactions.map { reaction -> ReactionNode in - return ReactionNode(account: self.account, theme: self.theme, reaction: reaction, maximizedReactionSize: maximizedReactionSize - 12.0, loadFirstFrame: true) - } - self.reactionNodes.forEach(self.addSubnode(_:)) - } - - let minimizedReactionVerticalInset: CGFloat = floor((backgroundHeight - minimizedReactionSize) / 2.0) - - - /*if maximizedIndex == -1 { - backgroundFrame.size.width -= maximizedReactionSize - minimizedReactionSize - backgroundFrame.origin.x += maximizedReactionSize - minimizedReactionSize - }*/ - - self.isRightAligned = isRightAligned - - let backgroundTransition: ContainedViewLayoutTransition - if isInitial { - backgroundTransition = .immediate - } else { - backgroundTransition = .animated(duration: 0.18, curve: .easeInOut) - } - backgroundTransition.updateFrame(node: self.backgroundNode, frame: backgroundFrame) - backgroundTransition.updateFrame(node: self.backgroundShadowNode, frame: backgroundFrame) - - var reactionX: CGFloat = backgroundFrame.minX + shadowBlur + reactionSideInset - if maximizedIndex != -1 { - self.hasSelectedNode = false - } else { - self.hasSelectedNode = true - } - - for iterationIndex in 0 ..< self.reactionNodes.count { - var i = iterationIndex - let isMaximized = i == maximizedIndex - if !isRightAligned { - i = self.reactionNodes.count - 1 - i - } - - let reactionSize: CGFloat - if isMaximized { - reactionSize = maximizedReactionSize - } else { - reactionSize = minimizedReactionSize - } - - let transition: ContainedViewLayoutTransition - if isInitial { - transition = .immediate - } else { - transition = .animated(duration: 0.18, curve: .easeInOut) - } - - if self.reactionNodes[i].isMaximized != isMaximized { - self.reactionNodes[i].isMaximized = isMaximized - self.reactionNodes[i].updateIsAnimating(isMaximized, animated: !isInitial) - if isMaximized && !isInitial { - self.hapticFeedback.tap() - } - } - - var reactionFrame = CGRect(origin: CGPoint(x: reactionX, y: backgroundFrame.maxY - shadowBlur - minimizedReactionVerticalInset - reactionSize), size: CGSize(width: reactionSize, height: reactionSize)) - if isMaximized { - reactionFrame.origin.x -= 7.0 - reactionFrame.size.width += 14.0 - } - self.reactionNodes[i].updateLayout(size: reactionFrame.size, scale: reactionFrame.size.width / (maximizedReactionSize + 14.0), transition: transition, displayText: isMaximized) - - transition.updateFrame(node: self.reactionNodes[i], frame: reactionFrame, beginWithCurrentState: true) - - reactionX += reactionSize + interReactionSpacing - } - - let mainBubbleFrame = CGRect(origin: CGPoint(x: anchorX - self.smallCircleSize - shadowBlur, y: backgroundFrame.maxY - shadowBlur - self.smallCircleSize - shadowBlur), size: CGSize(width: self.smallCircleSize * 2.0 + shadowBlur * 2.0, height: self.smallCircleSize * 2.0 + shadowBlur * 2.0)) - self.bubbleNodes[1].0.frame = mainBubbleFrame - self.bubbleNodes[1].1.frame = mainBubbleFrame - - let secondaryBubbleFrame = CGRect(origin: CGPoint(x: mainBubbleFrame.midX - 10.0 - (self.smallCircleSize + shadowBlur * 2.0) / 2.0, y: mainBubbleFrame.midY + 10.0 - (self.smallCircleSize + shadowBlur * 2.0) / 2.0), size: CGSize(width: self.smallCircleSize + shadowBlur * 2.0, height: self.smallCircleSize + shadowBlur * 2.0)) - self.bubbleNodes[0].0.frame = secondaryBubbleFrame - self.bubbleNodes[0].1.frame = secondaryBubbleFrame - } - - func animateIn() { - self.bubbleNodes[1].0.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - self.bubbleNodes[1].1.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.0, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - - self.bubbleNodes[0].0.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.05, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - self.bubbleNodes[0].1.layer.animateScale(from: 0.01, to: 1.0, duration: 0.11, delay: 0.05, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) - - let backgroundOffset: CGPoint - if self.isRightAligned { - backgroundOffset = CGPoint(x: (self.backgroundNode.frame.width - shadowBlur) / 2.0 - 42.0, y: 10.0) - } else { - backgroundOffset = CGPoint(x: -(self.backgroundNode.frame.width - shadowBlur) / 2.0 + 42.0, y: 10.0) - } - let damping: CGFloat = 100.0 - - for i in 0 ..< self.reactionNodes.count { - let animationOffset: Double = 1.0 - Double(i) / Double(self.reactionNodes.count - 1) - var nodeOffset: CGPoint - if self.isRightAligned { - nodeOffset = CGPoint(x: self.reactionNodes[i].frame.minX - (self.backgroundNode.frame.maxX - shadowBlur) / 2.0 - 42.0, y: 10.0) - } else { - nodeOffset = CGPoint(x: self.reactionNodes[i].frame.minX - (self.backgroundNode.frame.minX + shadowBlur) / 2.0 - 42.0, y: 10.0) - } - nodeOffset.x = 0.0 - nodeOffset.y = 30.0 - self.reactionNodes[i].layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.04, delay: animationOffset * 0.1) - self.reactionNodes[i].layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, delay: animationOffset * 0.1, initialVelocity: 0.0, damping: damping) - //self.reactionNodes[i].layer.animateSpring(from: NSValue(cgPoint: nodeOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, delay: animationOffset * 0.1, initialVelocity: 0.0, damping: damping, additive: true) - } - - self.backgroundNode.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, damping: damping) - self.backgroundNode.layer.animateSpring(from: NSValue(cgPoint: backgroundOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true) - self.backgroundShadowNode.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, damping: damping) - self.backgroundShadowNode.layer.animateSpring(from: NSValue(cgPoint: backgroundOffset), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: 0.5, initialVelocity: 0.0, damping: damping, additive: true) - } - - func animateOut(into targetNode: ASDisplayNode?, hideTarget: Bool, completion: @escaping () -> Void) { - self.hapticFeedback.prepareTap() - - var completedContainer = false - var completedTarget = true - - let intermediateCompletion: () -> Void = { - if completedContainer && completedTarget { - completion() - } - } - - if let targetNode = targetNode { - for i in 0 ..< self.reactionNodes.count { - if let isMaximized = self.reactionNodes[i].isMaximized, isMaximized { - targetNode.recursivelyEnsureDisplaySynchronously(true) - if let snapshotView = self.reactionNodes[i].view.snapshotContentTree(), let targetSnapshotView = targetNode.view.snapshotContentTree() { - targetSnapshotView.frame = self.view.convert(targetNode.bounds, from: targetNode.view) - self.reactionNodes[i].isHidden = true - self.view.addSubview(targetSnapshotView) - self.view.addSubview(snapshotView) - completedTarget = false - let targetPosition = self.view.convert(targetNode.bounds.center, from: targetNode.view) - let duration: Double = 0.3 - if hideTarget { - targetNode.isHidden = true - } - - snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false) - targetSnapshotView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - targetSnapshotView.layer.animateScale(from: snapshotView.bounds.width / targetSnapshotView.bounds.width, to: 0.5, duration: 0.3, removeOnCompletion: false) - - - let sourcePoint = snapshotView.center - let midPoint = CGPoint(x: (sourcePoint.x + targetPosition.x) / 2.0, y: sourcePoint.y - 30.0) - - let x1 = sourcePoint.x - let y1 = sourcePoint.y - let x2 = midPoint.x - let y2 = midPoint.y - let x3 = targetPosition.x - let y3 = targetPosition.y - - let a = (x3 * (y2 - y1) + x2 * (y1 - y3) + x1 * (y3 - y2)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - let b = (x1 * x1 * (y2 - y3) + x3 * x3 * (y1 - y2) + x2 * x2 * (y3 - y1)) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - let c = (x2 * x2 * (x3 * y1 - x1 * y3) + x2 * (x1 * x1 * y3 - x3 * x3 * y1) + x1 * x3 * (x3 - x1) * y2) / ((x1 - x2) * (x1 - x3) * (x2 - x3)) - - var keyframes: [AnyObject] = [] - for i in 0 ..< 10 { - let k = CGFloat(i) / CGFloat(10 - 1) - let x = sourcePoint.x * (1.0 - k) + targetPosition.x * k - let y = a * x * x + b * x + c - keyframes.append(NSValue(cgPoint: CGPoint(x: x, y: y))) - } - - snapshotView.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", removeOnCompletion: false, completion: { [weak self] _ in - if let strongSelf = self { - strongSelf.hapticFeedback.tap() - } - completedTarget = true - if hideTarget { - targetNode.isHidden = false - targetNode.layer.animateSpring(from: 0.5 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: duration, initialVelocity: 0.0, damping: 90.0) - } - intermediateCompletion() - }) - targetSnapshotView.layer.animateKeyframes(values: keyframes, duration: 0.3, keyPath: "position", removeOnCompletion: false) - - snapshotView.layer.animateScale(from: 1.0, to: (targetSnapshotView.bounds.width * 0.5) / snapshotView.bounds.width, duration: 0.3, removeOnCompletion: false) - } - break - } - } - } - - //self.backgroundNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - self.backgroundShadowNode.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - self.backgroundNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - self.backgroundShadowNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in - completedContainer = true - intermediateCompletion() - }) - for (node, shadow) in self.bubbleNodes { - node.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - node.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - shadow.layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - shadow.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - } - for i in 0 ..< self.reactionNodes.count { - self.reactionNodes[i].layer.animateScale(from: 1.0, to: 0.01, duration: 0.2, removeOnCompletion: false) - self.reactionNodes[i].layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) - } - } - - func selectedReaction() -> ReactionGestureItem? { - for i in 0 ..< self.reactionNodes.count { - if let isMaximized = self.reactionNodes[i].isMaximized, isMaximized { - return self.reactionNodes[i].reaction - } - } - return nil - } -} - diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSelectionParentNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionSelectionParentNode.swift deleted file mode 100644 index 7c3889ce76..0000000000 --- a/submodules/ReactionSelectionNode/Sources/ReactionSelectionParentNode.swift +++ /dev/null @@ -1,85 +0,0 @@ -import Foundation -import AsyncDisplayKit -import Display -import Postbox -import TelegramCore -import TelegramPresentationData - -public final class ReactionSelectionParentNode: ASDisplayNode { - private let account: Account - private let theme: PresentationTheme - - private var currentNode: ReactionSelectionNode? - private var currentLocation: (CGPoint, CGFloat, CGPoint)? - - private var validLayout: (size: CGSize, insets: UIEdgeInsets)? - - public init(account: Account, theme: PresentationTheme) { - self.account = account - self.theme = theme - - super.init() - } - - func displayReactions(_ reactions: [ReactionGestureItem], at point: CGPoint, touchPoint: CGPoint) { - if let currentNode = self.currentNode { - currentNode.removeFromSupernode() - self.currentNode = nil - } - - let reactionNode = ReactionSelectionNode(account: self.account, theme: self.theme, reactions: reactions) - self.addSubnode(reactionNode) - self.currentNode = reactionNode - self.currentLocation = (point, point.x, touchPoint) - - if let (size, insets) = self.validLayout { - self.update(size: size, insets: insets, isInitial: true) - - reactionNode.animateIn() - } - } - - func selectedReaction() -> ReactionGestureItem? { - if let currentNode = self.currentNode { - return currentNode.selectedReaction() - } - return nil - } - - func dismissReactions(into targetNode: ASDisplayNode?, hideTarget: Bool) { - if let currentNode = self.currentNode { - currentNode.animateOut(into: targetNode, hideTarget: hideTarget, completion: { [weak currentNode] in - currentNode?.removeFromSupernode() - }) - self.currentNode = nil - } - } - - func updateReactionsAnchor(point: CGPoint, touchPoint: CGPoint) { - if let (currentPoint, _, _) = self.currentLocation { - self.currentLocation = (currentPoint, point.x, touchPoint) - - if let (size, insets) = self.validLayout { - self.update(size: size, insets: insets, isInitial: false) - } - } - } - - public func updateLayout(size: CGSize, insets: UIEdgeInsets, transition: ContainedViewLayoutTransition) { - self.validLayout = (size, insets) - - self.update(size: size, insets: insets, isInitial: false) - } - - private func update(size: CGSize, insets: UIEdgeInsets, isInitial: Bool) { - if let currentNode = self.currentNode, let (point, offset, touchPoint) = self.currentLocation { - currentNode.updateLayout(constrainedSize: size, startingPoint: CGPoint(x: size.width - 32.0, y: point.y), offsetFromStart: offset, isInitial: isInitial, touchPoint: touchPoint) - currentNode.frame = CGRect(origin: CGPoint(), size: size) - } - } - - override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - return nil - } -} - diff --git a/submodules/ReactionSelectionNode/Sources/ReactionSwipeGestureRecognizer.swift b/submodules/ReactionSelectionNode/Sources/ReactionSwipeGestureRecognizer.swift deleted file mode 100644 index 44cc887651..0000000000 --- a/submodules/ReactionSelectionNode/Sources/ReactionSwipeGestureRecognizer.swift +++ /dev/null @@ -1,193 +0,0 @@ -import Foundation -import UIKit -import Display -import AsyncDisplayKit - -public final class ReactionSwipeGestureRecognizer: UIPanGestureRecognizer { - private var validatedGesture = false - - private var firstLocation: CGPoint = CGPoint() - private var currentLocation: CGPoint = CGPoint() - private var currentReactions: [ReactionGestureItem] = [] - private var isActivated = false - private var isAwaitingCompletion = false - private weak var currentContainer: ReactionSelectionParentNode? - private var activationTimer: Timer? - - public var availableReactions: (() -> [ReactionGestureItem])? - public var getReactionContainer: (() -> ReactionSelectionParentNode?)? - public var getAnchorPoint: (() -> CGPoint?)? - public var shouldElevateAnchorPoint: (() -> Bool)? - public var began: (() -> Void)? - public var updateOffset: ((CGFloat, Bool) -> Void)? - public var completed: ((ReactionGestureItem?) -> Void)? - public var displayReply: ((CGFloat) -> Void)? - public var activateReply: (() -> Void)? - - private var currentAnchorPoint: CGPoint? - private var currentAnchorStartPoint: CGPoint? - - override public init(target: Any?, action: Selector?) { - super.init(target: target, action: action) - - self.maximumNumberOfTouches = 1 - } - - override public func reset() { - super.reset() - - self.validatedGesture = false - self.currentReactions = [] - self.isActivated = false - self.isAwaitingCompletion = false - self.activationTimer?.invalidate() - self.activationTimer = nil - } - - override public func touchesBegan(_ touches: Set, with event: UIEvent) { - super.touchesBegan(touches, with: event) - - if let availableReactions = self.availableReactions?(), !availableReactions.isEmpty { - self.currentReactions = availableReactions - let touch = touches.first! - self.firstLocation = touch.location(in: nil) - self.currentLocation = self.firstLocation - } else { - self.state = .failed - } - } - - override public func touchesMoved(_ touches: Set, with event: UIEvent) { - if self.isAwaitingCompletion { - return - } - guard let _ = self.view else { - return - } - guard let location = touches.first?.location(in: nil) else { - return - } - self.currentLocation = location - - var translation = CGPoint(x: location.x - self.firstLocation.x, y: location.y - self.firstLocation.y) - - let absTranslationX: CGFloat = abs(translation.x) - let absTranslationY: CGFloat = abs(translation.y) - - var updatedOffset = false - - if !self.validatedGesture { - if translation.x > 0.0 { - self.state = .failed - } else if absTranslationY > 2.0 && absTranslationY > absTranslationX * 2.0 { - self.state = .failed - } else if absTranslationX > 2.0 && absTranslationY * 2.0 < absTranslationX { - self.validatedGesture = true - self.firstLocation = location - translation = CGPoint() - self.began?() - self.updateOffset?(0.0, false) - updatedOffset = true - - self.activationTimer?.invalidate() - final class TimerTarget: NSObject { - let f: () -> Void - - init(_ f: @escaping () -> Void) { - self.f = f - } - - @objc func event() { - self.f() - } - } - let elevate = self.shouldElevateAnchorPoint?() ?? false - - let activationTimer = Timer(timeInterval: elevate ? 0.15 : 0.01, target: TimerTarget { [weak self] in - guard let strongSelf = self else { - return - } - strongSelf.activationTimer = nil - if strongSelf.validatedGesture { - let location = strongSelf.currentLocation - if !strongSelf.currentReactions.isEmpty, let reactionContainer = strongSelf.getReactionContainer?(), let _ = strongSelf.getAnchorPoint?() { - strongSelf.currentContainer = reactionContainer - //let reactionContainerLocation = reactionContainer.view.convert(localAnchorPoint, from: strongSelf.view) - let elevate = strongSelf.shouldElevateAnchorPoint?() ?? false - let reactionContainerLocation = reactionContainer.view.convert(location, from: nil).offsetBy(dx: 0.0, dy: elevate ? -44.0 : 22.0) - let reactionContainerTouchPoint = reactionContainer.view.convert(location, from: nil) - strongSelf.currentAnchorPoint = reactionContainerLocation - strongSelf.currentAnchorStartPoint = location - reactionContainer.displayReactions(strongSelf.currentReactions, at: reactionContainerLocation, touchPoint: reactionContainerTouchPoint) - } - } - }, selector: #selector(TimerTarget.event), userInfo: nil, repeats: false) - self.activationTimer = activationTimer - RunLoop.main.add(activationTimer, forMode: .common) - } - } - - if self.validatedGesture { - if !updatedOffset { - self.updateOffset?(-min(0.0, translation.x), false) - } - if !self.isActivated { - if absTranslationX > 40.0 { - self.isActivated = true - self.displayReply?(-min(0.0, translation.x)) - } - } else { - if let reactionContainer = self.currentContainer, let currentAnchorPoint = self.currentAnchorPoint, let currentAnchorStartPoint = self.currentAnchorStartPoint { - let anchorPoint = CGPoint(x: currentAnchorPoint.x + location.x - currentAnchorStartPoint.x, y: currentAnchorPoint.y) - let reactionContainerLocation = anchorPoint - let reactionContainerTouchPoint = reactionContainer.view.convert(location, from: nil) - reactionContainer.updateReactionsAnchor(point: reactionContainerLocation, touchPoint: reactionContainerTouchPoint) - } - } - super.touchesMoved(touches, with: event) - } - } - - override public func touchesEnded(_ touches: Set, with event: UIEvent) { - if self.isAwaitingCompletion { - return - } - guard let location = touches.first?.location(in: nil) else { - return - } - if self.validatedGesture { - let translation = CGPoint(x: location.x - self.firstLocation.x, y: location.y - self.firstLocation.y) - if let reaction = self.currentContainer?.selectedReaction() { - self.isAwaitingCompletion = true - self.completed?(reaction) - } else { - if translation.x < -40.0 { - self.currentContainer?.dismissReactions(into: nil, hideTarget: false) - self.activateReply?() - self.state = .ended - } else { - self.currentContainer?.dismissReactions(into: nil, hideTarget: false) - self.completed?(nil) - self.state = .cancelled - super.touchesEnded(touches, with: event) - } - } - } else { - self.currentContainer?.dismissReactions(into: nil, hideTarget: false) - self.state = .cancelled - super.touchesEnded(touches, with: event) - } - } - - public func complete(into targetNode: ASDisplayNode?, hideTarget: Bool) { - if self.isAwaitingCompletion { - self.currentContainer?.dismissReactions(into: targetNode, hideTarget: hideTarget) - self.state = .ended - } - } - - public func cancel() { - self.state = .cancelled - } -} - diff --git a/submodules/SelectablePeerNode/BUILD b/submodules/SelectablePeerNode/BUILD index 752fbcac44..3ab6648992 100644 --- a/submodules/SelectablePeerNode/BUILD +++ b/submodules/SelectablePeerNode/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index 90f64cb3d1..cf8ddebb65 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -804,7 +804,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The }))) } - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: themeController, sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: themeController, sourceNode: node)), items: .single(ContextController.Items(items: items)), gesture: gesture) presentInGlobalOverlayImpl?(contextController, nil) }) }, colorContextAction: { isCurrent, reference, accentColor, node, gesture in @@ -1041,7 +1041,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } } } - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: themeController, sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: themeController, sourceNode: node)), items: .single(ContextController.Items(items: items)), gesture: gesture) presentInGlobalOverlayImpl?(contextController, nil) }) }) diff --git a/submodules/SlotMachineAnimationNode/BUILD b/submodules/SlotMachineAnimationNode/BUILD index 9ebdcc588e..6c660b314e 100644 --- a/submodules/SlotMachineAnimationNode/BUILD +++ b/submodules/SlotMachineAnimationNode/BUILD @@ -13,7 +13,6 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AsyncDisplayKit:AsyncDisplayKit", "//submodules/Display:Display", - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/AccountContext:AccountContext", "//submodules/StickerResources:StickerResources", diff --git a/submodules/SlotMachineAnimationNode/Sources/SlotMachineAnimationNode.swift b/submodules/SlotMachineAnimationNode/Sources/SlotMachineAnimationNode.swift index f12f6816a7..e14f224e66 100644 --- a/submodules/SlotMachineAnimationNode/Sources/SlotMachineAnimationNode.swift +++ b/submodules/SlotMachineAnimationNode/Sources/SlotMachineAnimationNode.swift @@ -1,7 +1,6 @@ import Foundation import Display import AsyncDisplayKit -import Postbox import TelegramCore import SwiftSignalKit import StickerResources diff --git a/submodules/StatisticsUI/Sources/ChannelStatsController.swift b/submodules/StatisticsUI/Sources/ChannelStatsController.swift index aa1b95f4f6..1cf81bf1b5 100644 --- a/submodules/StatisticsUI/Sources/ChannelStatsController.swift +++ b/submodules/StatisticsUI/Sources/ChannelStatsController.swift @@ -523,7 +523,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD }) }))) - let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(ChannelStatsContextExtractedContentSource(controller: controller, sourceNode: sourceNode, keepInPlace: false)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: context.account, presentationData: presentationData, source: .extracted(ChannelStatsContextExtractedContentSource(controller: controller, sourceNode: sourceNode, keepInPlace: false)), items: .single(ContextController.Items(items: items)), gesture: gesture) controller.presentInGlobalOverlay(contextController) } return controller diff --git a/submodules/StatisticsUI/Sources/StatsMessageItem.swift b/submodules/StatisticsUI/Sources/StatsMessageItem.swift index 512eac52d2..eaee3b6b98 100644 --- a/submodules/StatisticsUI/Sources/StatsMessageItem.swift +++ b/submodules/StatisticsUI/Sources/StatsMessageItem.swift @@ -241,7 +241,7 @@ public class StatsMessageItemNode: ListViewItemNode, ItemListItemNode { let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize) let presentationData = item.context.sharedContext.currentPresentationData.with { $0 } - let contentKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: item.message, strings: item.presentationData.strings, nameDisplayOrder: .firstLast, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId) + let contentKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(item.message), strings: item.presentationData.strings, nameDisplayOrder: .firstLast, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId) var text = !item.message.text.isEmpty ? item.message.text : stringForMediaKind(contentKind, strings: item.presentationData.strings).0 text = foldLineBreaks(text) diff --git a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift index 4b62b4d876..304b18d52c 100644 --- a/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift +++ b/submodules/TelegramBaseController/Sources/MediaNavigationAccessoryHeaderNode.swift @@ -555,7 +555,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi return } let items: Signal<[ContextMenuItem], NoError> = self.contextMenuSpeedItems() - let contextController = ContextController(account: self.context.account, presentationData: self.context.sharedContext.currentPresentationData.with { $0 }, source: .reference(HeaderContextReferenceContentSource(controller: controller, sourceNode: self.rateButton.referenceNode, shouldBeDismissed: self.dismissedPromise.get())), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: self.context.account, presentationData: self.context.sharedContext.currentPresentationData.with { $0 }, source: .reference(HeaderContextReferenceContentSource(controller: controller, sourceNode: self.rateButton.referenceNode, shouldBeDismissed: self.dismissedPromise.get())), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) self.presentInGlobalOverlay?(contextController) } diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index 275e8a9033..f200e2579e 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -1791,7 +1791,7 @@ public final class VoiceChatController: ViewController { dismissPromise.set(true) } - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme), source: .extracted(source), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData.withUpdated(theme: strongSelf.darkTheme), source: .extracted(source), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) contextController.useComplexItemsTransitionAnimation = true strongSelf.controller?.presentInGlobalOverlay(contextController) }, getPeerVideo: { [weak self] endpointId, position in @@ -2458,7 +2458,7 @@ public final class VoiceChatController: ViewController { private func openSettingsMenu(sourceNode: ASDisplayNode, gesture: ContextGesture?) { let items: Signal<[ContextMenuItem], NoError> = self.contextMenuMainItems() if let controller = self.controller { - let contextController = ContextController(account: self.context.account, presentationData: self.presentationData.withUpdated(theme: self.darkTheme), source: .reference(VoiceChatContextReferenceContentSource(controller: controller, sourceNode: self.optionsButton.referenceNode)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: self.context.account, presentationData: self.presentationData.withUpdated(theme: self.darkTheme), source: .reference(VoiceChatContextReferenceContentSource(controller: controller, sourceNode: self.optionsButton.referenceNode)), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) controller.presentInGlobalOverlay(contextController) } } diff --git a/submodules/TelegramCore/Sources/Account/Account.swift b/submodules/TelegramCore/Sources/Account/Account.swift index 78fd20753c..e35af6f9e3 100644 --- a/submodules/TelegramCore/Sources/Account/Account.swift +++ b/submodules/TelegramCore/Sources/Account/Account.swift @@ -1020,7 +1020,6 @@ public class Account { self.managedOperationsDisposable.add(managedSynchronizeConsumeMessageContentOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedConsumePersonalMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedSynchronizeMarkAllUnseenPersonalMessagesOperations(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) - self.managedOperationsDisposable.add(managedApplyPendingMessageReactionsActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) self.managedOperationsDisposable.add(managedSynchronizeEmojiKeywordsOperations(postbox: self.postbox, network: self.network).start()) self.managedOperationsDisposable.add(managedApplyPendingScheduledMessagesActions(postbox: self.postbox, network: self.network, stateManager: self.stateManager).start()) diff --git a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift index 99c1264e63..b610a5dd6b 100644 --- a/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift +++ b/submodules/TelegramCore/Sources/Account/AccountIntermediateState.swift @@ -258,10 +258,6 @@ struct AccountMutableState { self.addOperation(.UpdateMessagePoll(id, poll, results)) } - /*mutating func updateMessageReactions(_ messageId: MessageId, reactions: Api.MessageReactions) { - self.addOperation(.UpdateMessageReactions(messageId, reactions)) - }*/ - mutating func updateMedia(_ id: MediaId, media: Media?) { self.addOperation(.UpdateMedia(id, media)) } diff --git a/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift b/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift deleted file mode 100644 index b435a2919a..0000000000 --- a/submodules/TelegramCore/Sources/ApiUtils/ReactionsMessageAttribute.swift +++ /dev/null @@ -1,101 +0,0 @@ -import Foundation -import Postbox -import TelegramApi - - -/*extension ReactionsMessageAttribute { - func withUpdatedResults(_ reactions: Api.MessageReactions) -> ReactionsMessageAttribute { - switch reactions { - case let .messageReactions(flags, results): - let min = (flags & (1 << 0)) != 0 - var reactions = results.map { result -> MessageReaction in - switch result { - case let .reactionCount(flags, reaction, count): - return MessageReaction(value: reaction, count: count, isSelected: (flags & (1 << 0)) != 0) - } - } - if min { - var currentSelectedReaction: String? - for reaction in self.reactions { - if reaction.isSelected { - currentSelectedReaction = reaction.value - break - } - } - if let currentSelectedReaction = currentSelectedReaction { - for i in 0 ..< reactions.count { - if reactions[i].value == currentSelectedReaction { - reactions[i].isSelected = true - } - } - } - } - return ReactionsMessageAttribute(reactions: reactions) - } - } -}*/ - -public func mergedMessageReactions(attributes: [MessageAttribute]) -> ReactionsMessageAttribute? { - var current: ReactionsMessageAttribute? - var pending: PendingReactionsMessageAttribute? - for attribute in attributes { - if let attribute = attribute as? ReactionsMessageAttribute { - current = attribute - } else if let attribute = attribute as? PendingReactionsMessageAttribute { - pending = attribute - } - } - - if let pending = pending { - var reactions = current?.reactions ?? [] - if let value = pending.value { - var found = false - for i in 0 ..< reactions.count { - if reactions[i].value == value { - found = true - if !reactions[i].isSelected { - reactions[i].isSelected = true - reactions[i].count += 1 - } - } - } - if !found { - reactions.append(MessageReaction(value: value, count: 1, isSelected: true)) - } - } - for i in (0 ..< reactions.count).reversed() { - if reactions[i].isSelected, pending.value != reactions[i].value { - if reactions[i].count == 1 { - reactions.remove(at: i) - } else { - reactions[i].isSelected = false - reactions[i].count -= 1 - } - } - } - if !reactions.isEmpty { - return ReactionsMessageAttribute(reactions: reactions) - } else { - return nil - } - } else if let current = current { - return current - } else { - return nil - } -} - -/*extension ReactionsMessageAttribute { - convenience init(apiReactions: Api.MessageReactions) { - switch apiReactions { - case let .messageReactions(_, results): - self.init(reactions: results.map { result in - switch result { - case let .reactionCount(flags, reaction, count): - return MessageReaction(value: reaction, count: count, isSelected: (flags & (1 << 0)) != 0) - } - }) - } - } -} -*/ diff --git a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index 9eb5c48031..c04933a70f 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift @@ -546,10 +546,6 @@ extension StoreMessage { attributes.append(ContentRequiresValidationMessageAttribute()) } - /*if let reactions = reactions { - attributes.append(ReactionsMessageAttribute(apiReactions: reactions)) - }*/ - if let replies = replies { let recentRepliersPeerIds: [PeerId]? switch replies { diff --git a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index aa6f2933ba..6c3086212e 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift @@ -648,7 +648,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, if !hasHiddenForwardMedia { var sourceId: PeerId? = nil var sourceMessageId: MessageId? = nil - if let peer = messageMainPeer(sourceMessage) as? TelegramChannel, case .broadcast = peer.info { + if case let .channel(peer) = messageMainPeer(EngineMessage(sourceMessage)), case .broadcast = peer.info { sourceId = peer.id sourceMessageId = sourceMessage.id } diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index a489df1672..0265b043b2 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1381,8 +1381,6 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo updatedState.updateLangPack(langCode: langCode, difference: difference) case let .updateMessagePoll(_, pollId, poll, results): updatedState.updateMessagePoll(MediaId(namespace: Namespaces.Media.CloudPoll, id: pollId), poll: poll, results: results) - /*case let .updateMessageReactions(peer, msgId, reactions): - updatedState.updateMessageReactions(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), reactions: reactions)*/ case let .updateFolderPeers(folderPeers, _, _): for folderPeer in folderPeers { switch folderPeer { @@ -2685,26 +2683,6 @@ func replayFinalState( updatedPoll = updatedPoll.withUpdatedResults(TelegramMediaPollResults(apiResults: results), min: resultsMin) updateMessageMedia(transaction: transaction, id: pollId, media: updatedPoll) } - /*case let .UpdateMessageReactions(messageId, reactions): - transaction.updateMessage(messageId, update: { currentMessage in - var storeForwardInfo: StoreMessageForwardInfo? - if let forwardInfo = currentMessage.forwardInfo { - storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags) - } - var attributes = currentMessage.attributes - var found = false - loop: for j in 0 ..< attributes.count { - if let attribute = attributes[j] as? ReactionsMessageAttribute { - attributes[j] = attribute.withUpdatedResults(reactions) - found = true - break loop - } - } - if !found { - attributes.append(ReactionsMessageAttribute(apiReactions: reactions)) - } - return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) - })*/ case let .UpdateMedia(id, media): if let media = media as? TelegramMediaWebpage { updatedWebpages[id] = media diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index b2b667e250..81667079b8 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -812,89 +812,6 @@ public final class AccountViewTracker { } } - public func updateReactionsForMessageIds(messageIds: Set) { - /*self.queue.async { - var addedMessageIds: [MessageId] = [] - let timestamp = Int32(CFAbsoluteTimeGetCurrent()) - for messageId in messageIds { - let messageTimestamp = self.updatedReactionsMessageIdsAndTimestamps[messageId] - if messageTimestamp == nil || messageTimestamp! < timestamp - 5 * 60 { - self.updatedReactionsMessageIdsAndTimestamps[messageId] = timestamp - addedMessageIds.append(messageId) - } - } - if !addedMessageIds.isEmpty { - for (peerId, messageIds) in messagesIdsGroupedByPeerId(Set(addedMessageIds)) { - let disposableId = self.nextUpdatedReactionsDisposableId - self.nextUpdatedReactionsDisposableId += 1 - - if let account = self.account { - let signal = (account.postbox.transaction { transaction -> Signal in - if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { - return account.network.request(Api.functions.messages.getMessagesReactions(peer: inputPeer, id: messageIds.map { $0.id })) - |> map(Optional.init) - |> `catch` { _ -> Signal in - return .single(nil) - } - |> mapToSignal { updates -> Signal in - guard let updates = updates else { - return .complete() - } - return account.postbox.transaction { transaction -> Void in - let updateList: [Api.Update] - switch updates { - case let .updates(updates, _, _, _, _): - updateList = updates - case let .updatesCombined(updates, _, _, _, _, _): - updateList = updates - case let .updateShort(update, _): - updateList = [update] - default: - updateList = [] - } - for update in updateList { - switch update { - case let .updateMessageReactions(peer, msgId, reactions): - transaction.updateMessage(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: msgId), update: { currentMessage in - - let updatedReactions = ReactionsMessageAttribute(apiReactions: reactions) - - let storeForwardInfo = currentMessage.forwardInfo.flatMap(StoreMessageForwardInfo.init) - var attributes = currentMessage.attributes - loop: for j in 0 ..< attributes.count { - if let attribute = attributes[j] as? ReactionsMessageAttribute { - if updatedReactions.reactions == attribute.reactions { - return .skip - } - attributes[j] = updatedReactions - break loop - } - } - return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) - }) - default: - break - } - } - } - } - } else { - return .complete() - } - } - |> switchToLatest) - |> afterDisposed { [weak self] in - self?.queue.async { - self?.updatedReactionsDisposables.set(nil, forKey: disposableId) - } - } - self.updatedReactionsDisposables.set(signal.start(), forKey: disposableId) - } - } - } - }*/ - } - public func updateSeenLiveLocationForMessageIds(messageIds: Set) { self.queue.async { var addedMessageIds: [MessageId] = [] diff --git a/submodules/TelegramCore/Sources/State/MessageReactions.swift b/submodules/TelegramCore/Sources/State/MessageReactions.swift deleted file mode 100644 index 87d43ad2d6..0000000000 --- a/submodules/TelegramCore/Sources/State/MessageReactions.swift +++ /dev/null @@ -1,227 +0,0 @@ -import Foundation -import Postbox -import SwiftSignalKit -import TelegramApi -import MtProtoKit - - -public func updateMessageReactionsInteractively(postbox: Postbox, messageId: MessageId, reaction: String?) -> Signal { - return postbox.transaction { transaction -> Void in - transaction.setPendingMessageAction(type: .updateReaction, id: messageId, action: UpdateMessageReactionsAction()) - transaction.updateMessage(messageId, update: { currentMessage in - var storeForwardInfo: StoreMessageForwardInfo? - if let forwardInfo = currentMessage.forwardInfo { - storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags) - } - var attributes = currentMessage.attributes - loop: for j in 0 ..< attributes.count { - if let _ = attributes[j] as? PendingReactionsMessageAttribute { - attributes.remove(at: j) - break loop - } - } - attributes.append(PendingReactionsMessageAttribute(value: reaction)) - return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) - }) - } - |> ignoreValues -} - -private enum RequestUpdateMessageReactionError { - case generic -} - -private func requestUpdateMessageReaction(postbox: Postbox, network: Network, stateManager: AccountStateManager, messageId: MessageId) -> Signal { - return .complete() - /*return postbox.transaction { transaction -> (Peer, String?)? in - guard let peer = transaction.getPeer(messageId.peerId) else { - return nil - } - guard let message = transaction.getMessage(messageId) else { - return nil - } - var value: String? - for attribute in message.attributes { - if let attribute = attribute as? PendingReactionsMessageAttribute { - value = attribute.value - break - } - } - return (peer, value) - } - |> castError(RequestUpdateMessageReactionError.self) - |> mapToSignal { peerAndValue in - guard let (peer, value) = peerAndValue else { - return .fail(.generic) - } - guard let inputPeer = apiInputPeer(peer) else { - return .fail(.generic) - } - if messageId.namespace != Namespaces.Message.Cloud { - return .fail(.generic) - } - return network.request(Api.functions.messages.sendReaction(flags: value == nil ? 0 : 1, peer: inputPeer, msgId: messageId.id, reaction: value)) - |> mapError { _ -> RequestUpdateMessageReactionError in - return .generic - } - |> mapToSignal { result -> Signal in - return postbox.transaction { transaction -> Void in - transaction.setPendingMessageAction(type: .updateReaction, id: messageId, action: UpdateMessageReactionsAction()) - transaction.updateMessage(messageId, update: { currentMessage in - var storeForwardInfo: StoreMessageForwardInfo? - if let forwardInfo = currentMessage.forwardInfo { - storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags) - } - let reactions = mergedMessageReactions(attributes: currentMessage.attributes) - var attributes = currentMessage.attributes - for j in (0 ..< attributes.count).reversed() { - if attributes[j] is PendingReactionsMessageAttribute || attributes[j] is ReactionsMessageAttribute { - attributes.remove(at: j) - } - } - if let reactions = reactions { - attributes.append(reactions) - } - return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) - }) - stateManager.addUpdates(result) - } - |> castError(RequestUpdateMessageReactionError.self) - |> ignoreValues - } - }*/ -} - -private final class ManagedApplyPendingMessageReactionsActionsHelper { - var operationDisposables: [MessageId: Disposable] = [:] - - func update(entries: [PendingMessageActionsEntry]) -> (disposeOperations: [Disposable], beginOperations: [(PendingMessageActionsEntry, MetaDisposable)]) { - var disposeOperations: [Disposable] = [] - var beginOperations: [(PendingMessageActionsEntry, MetaDisposable)] = [] - - var hasRunningOperationForPeerId = Set() - var validIds = Set() - for entry in entries { - if !hasRunningOperationForPeerId.contains(entry.id.peerId) { - hasRunningOperationForPeerId.insert(entry.id.peerId) - validIds.insert(entry.id) - - if self.operationDisposables[entry.id] == nil { - let disposable = MetaDisposable() - beginOperations.append((entry, disposable)) - self.operationDisposables[entry.id] = disposable - } - } - } - - var removeMergedIds: [MessageId] = [] - for (id, disposable) in self.operationDisposables { - if !validIds.contains(id) { - removeMergedIds.append(id) - disposeOperations.append(disposable) - } - } - - for id in removeMergedIds { - self.operationDisposables.removeValue(forKey: id) - } - - return (disposeOperations, beginOperations) - } - - func reset() -> [Disposable] { - let disposables = Array(self.operationDisposables.values) - self.operationDisposables.removeAll() - return disposables - } -} - -private func withTakenAction(postbox: Postbox, type: PendingMessageActionType, id: MessageId, _ f: @escaping (Transaction, PendingMessageActionsEntry?) -> Signal) -> Signal { - return postbox.transaction { transaction -> Signal in - var result: PendingMessageActionsEntry? - - if let action = transaction.getPendingMessageAction(type: type, id: id) as? UpdateMessageReactionsAction { - result = PendingMessageActionsEntry(id: id, action: action) - } - - return f(transaction, result) - } - |> switchToLatest -} - -func managedApplyPendingMessageReactionsActions(postbox: Postbox, network: Network, stateManager: AccountStateManager) -> Signal { - return Signal { _ in - let helper = Atomic(value: ManagedApplyPendingMessageReactionsActionsHelper()) - - let actionsKey = PostboxViewKey.pendingMessageActions(type: .updateReaction) - let disposable = postbox.combinedView(keys: [actionsKey]).start(next: { view in - var entries: [PendingMessageActionsEntry] = [] - if let v = view.views[actionsKey] as? PendingMessageActionsView { - entries = v.entries - } - - let (disposeOperations, beginOperations) = helper.with { helper -> (disposeOperations: [Disposable], beginOperations: [(PendingMessageActionsEntry, MetaDisposable)]) in - return helper.update(entries: entries) - } - - for disposable in disposeOperations { - disposable.dispose() - } - - for (entry, disposable) in beginOperations { - let signal = withTakenAction(postbox: postbox, type: .updateReaction, id: entry.id, { transaction, entry -> Signal in - if let entry = entry { - if let _ = entry.action as? UpdateMessageReactionsAction { - return synchronizeMessageReactions(transaction: transaction, postbox: postbox, network: network, stateManager: stateManager, id: entry.id) - } else { - assertionFailure() - } - } - return .complete() - }) - |> then( - postbox.transaction { transaction -> Void in - transaction.setPendingMessageAction(type: .updateReaction, id: entry.id, action: nil) - } - |> ignoreValues - ) - - disposable.set(signal.start()) - } - }) - - return ActionDisposable { - let disposables = helper.with { helper -> [Disposable] in - return helper.reset() - } - for disposable in disposables { - disposable.dispose() - } - disposable.dispose() - } - } -} - -private func synchronizeMessageReactions(transaction: Transaction, postbox: Postbox, network: Network, stateManager: AccountStateManager, id: MessageId) -> Signal { - return requestUpdateMessageReaction(postbox: postbox, network: network, stateManager: stateManager, messageId: id) - |> `catch` { _ -> Signal in - return postbox.transaction { transaction -> Void in - transaction.setPendingMessageAction(type: .updateReaction, id: id, action: nil) - transaction.updateMessage(id, update: { currentMessage in - var storeForwardInfo: StoreMessageForwardInfo? - if let forwardInfo = currentMessage.forwardInfo { - storeForwardInfo = StoreMessageForwardInfo(authorId: forwardInfo.author?.id, sourceId: forwardInfo.source?.id, sourceMessageId: forwardInfo.sourceMessageId, date: forwardInfo.date, authorSignature: forwardInfo.authorSignature, psaType: forwardInfo.psaType, flags: forwardInfo.flags) - } - var attributes = currentMessage.attributes - loop: for j in 0 ..< attributes.count { - if let _ = attributes[j] as? PendingReactionsMessageAttribute { - attributes.remove(at: j) - break loop - } - } - return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, threadId: currentMessage.threadId, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) - }) - } - |> ignoreValues - } -} diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift index e281a8614f..4a1898a5c5 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_ReactionsMessageAttribute.swift @@ -1,42 +1,13 @@ import Postbox -public struct MessageReaction: Equatable, PostboxCoding { - public var value: String - public var count: Int32 - public var isSelected: Bool - - public init(value: String, count: Int32, isSelected: Bool) { - self.value = value - self.count = count - self.isSelected = isSelected - } - - public init(decoder: PostboxDecoder) { - self.value = decoder.decodeStringForKey("v", orElse: "") - self.count = decoder.decodeInt32ForKey("c", orElse: 0) - self.isSelected = decoder.decodeInt32ForKey("s", orElse: 0) != 0 - } - - public func encode(_ encoder: PostboxEncoder) { - encoder.encodeString(self.value, forKey: "v") - encoder.encodeInt32(self.count, forKey: "c") - encoder.encodeInt32(self.isSelected ? 1 : 0, forKey: "s") - } -} - public final class ReactionsMessageAttribute: MessageAttribute { - public let reactions: [MessageReaction] - - public init(reactions: [MessageReaction]) { - self.reactions = reactions + public init() { } required public init(decoder: PostboxDecoder) { - self.reactions = decoder.decodeObjectArrayWithDecoderForKey("r") } public func encode(_ encoder: PostboxEncoder) { - encoder.encodeObjectArray(self.reactions, forKey: "r") } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Media.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Media.swift index 9b3a40c891..b83f597780 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/Media.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/Media.swift @@ -2,4 +2,84 @@ import Postbox public enum EngineMedia { public typealias Id = MediaId + + case image(TelegramMediaImage) + case file(TelegramMediaFile) + case geo(TelegramMediaMap) + case contact(TelegramMediaContact) + case action(TelegramMediaAction) + case dice(TelegramMediaDice) + case expiredContent(TelegramMediaExpiredContent) + case game(TelegramMediaGame) + case invoice(TelegramMediaInvoice) + case poll(TelegramMediaPoll) + case unsupported(TelegramMediaUnsupported) + case webFile(TelegramMediaWebFile) + case webpage(TelegramMediaWebpage) +} + +public extension EngineMedia { + init(_ media: Media) { + switch media { + case let image as TelegramMediaImage: + self = .image(image) + case let file as TelegramMediaFile: + self = .file(file) + case let geo as TelegramMediaMap: + self = .geo(geo) + case let contact as TelegramMediaContact: + self = .contact(contact) + case let action as TelegramMediaAction: + self = .action(action) + case let dice as TelegramMediaDice: + self = .dice(dice) + case let expiredContent as TelegramMediaExpiredContent: + self = .expiredContent(expiredContent) + case let game as TelegramMediaGame: + self = .game(game) + case let invoice as TelegramMediaInvoice: + self = .invoice(invoice) + case let poll as TelegramMediaPoll: + self = .poll(poll) + case let unsupported as TelegramMediaUnsupported: + self = .unsupported(unsupported) + case let webFile as TelegramMediaWebFile: + self = .webFile(webFile) + case let webpage as TelegramMediaWebpage: + self = .webpage(webpage) + default: + preconditionFailure() + } + } + + func _asMedia() -> Media { + switch self { + case let .image(image): + return image + case let .file(file): + return file + case let .geo(geo): + return geo + case let .contact(contact): + return contact + case let .action(action): + return action + case let .dice(dice): + return dice + case let .expiredContent(expiredContent): + return expiredContent + case let .game(game): + return game + case let .invoice(invoice): + return invoice + case let .poll(poll): + return poll + case let .unsupported(unsupported): + return unsupported + case let .webFile(webFile): + return webFile + case let .webpage(webpage): + return webpage + } + } } diff --git a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift index 5efc7e35d6..ddbf97a2de 100644 --- a/submodules/TelegramCore/Sources/Utils/PeerUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/PeerUtils.swift @@ -194,12 +194,12 @@ public func peerDebugDisplayTitles(_ peers: [Peer]) -> String { } } -public func messageMainPeer(_ message: Message) -> Peer? { +public func messageMainPeer(_ message: EngineMessage) -> EnginePeer? { if let peer = message.peers[message.id.peerId] { if let peer = peer as? TelegramSecretChat { - return message.peers[peer.regularPeerId] + return message.peers[peer.regularPeerId].flatMap(EnginePeer.init) } else { - return peer + return EnginePeer(peer) } } else { return nil diff --git a/submodules/TelegramPermissions/BUILD b/submodules/TelegramPermissions/BUILD index 5c9010b5d7..a5fb22cea8 100644 --- a/submodules/TelegramPermissions/BUILD +++ b/submodules/TelegramPermissions/BUILD @@ -10,7 +10,6 @@ swift_library( "-warnings-as-errors", ], deps = [ - "//submodules/Postbox:Postbox", "//submodules/TelegramCore:TelegramCore", "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/AccountContext:AccountContext", diff --git a/submodules/TelegramPermissions/Sources/Permission.swift b/submodules/TelegramPermissions/Sources/Permission.swift index dc7a30d5cc..02f94db8df 100644 --- a/submodules/TelegramPermissions/Sources/Permission.swift +++ b/submodules/TelegramPermissions/Sources/Permission.swift @@ -1,6 +1,5 @@ import Foundation import SwiftSignalKit -import Postbox import TelegramCore import DeviceAccess import AccountContext diff --git a/submodules/TelegramStringFormatting/BUILD b/submodules/TelegramStringFormatting/BUILD index 9c917401d3..932916cf5c 100644 --- a/submodules/TelegramStringFormatting/BUILD +++ b/submodules/TelegramStringFormatting/BUILD @@ -11,7 +11,6 @@ swift_library( ], deps = [ "//submodules/TelegramCore:TelegramCore", - "//submodules/Postbox:Postbox", "//submodules/Display:Display", "//submodules/PlatformRestrictionMatching:PlatformRestrictionMatching", "//submodules/LocalizedPeerData:LocalizedPeerData", diff --git a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift index 5cd5cb9b08..e51050345e 100644 --- a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift +++ b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift @@ -1,5 +1,4 @@ import Foundation -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -88,7 +87,7 @@ public enum MessageContentKind: Equatable { } } -public func messageContentKind(contentSettings: ContentSettings, message: Message, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: PeerId) -> MessageContentKind { +public func messageContentKind(contentSettings: ContentSettings, message: EngineMessage, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: EnginePeer.Id) -> MessageContentKind { for attribute in message.attributes { if let attribute = attribute as? RestrictedContentMessageAttribute { if let text = attribute.platformText(platform: "ios", contentSettings: contentSettings) { @@ -98,25 +97,25 @@ public func messageContentKind(contentSettings: ContentSettings, message: Messag } } for media in message.media { - if let kind = mediaContentKind(media, message: message, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId) { + if let kind = mediaContentKind(EngineMedia(media), message: message, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId) { return kind } } return .text(message.text) } -public func mediaContentKind(_ media: Media, message: Message? = nil, strings: PresentationStrings? = nil, nameDisplayOrder: PresentationPersonNameOrder? = nil, dateTimeFormat: PresentationDateTimeFormat? = nil, accountPeerId: PeerId? = nil) -> MessageContentKind? { +public func mediaContentKind(_ media: EngineMedia, message: EngineMessage? = nil, strings: PresentationStrings? = nil, nameDisplayOrder: PresentationPersonNameOrder? = nil, dateTimeFormat: PresentationDateTimeFormat? = nil, accountPeerId: EnginePeer.Id? = nil) -> MessageContentKind? { switch media { - case let expiredMedia as TelegramMediaExpiredContent: + case let .expiredContent(expiredMedia): switch expiredMedia.data { case .image: return .expiredImage case .file: return .expiredVideo } - case _ as TelegramMediaImage: + case .image: return .image - case let file as TelegramMediaFile: + case let .file(file): var fileName: String = "" for attribute in file.attributes { switch attribute { @@ -154,27 +153,27 @@ public func mediaContentKind(_ media: Media, message: Message? = nil, strings: P return .sticker("") } return .file(fileName) - case _ as TelegramMediaContact: + case .contact: return .contact - case let game as TelegramMediaGame: + case let .game(game): return .game(game.title) - case let location as TelegramMediaMap: + case let .geo(location): if location.liveBroadcastingTimeout != nil { return .liveLocation } else { return .location } - case _ as TelegramMediaAction: + case .action: if let message = message, let strings = strings, let nameDisplayOrder = nameDisplayOrder, let accountPeerId = accountPeerId { return .text(plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat ?? PresentationDateTimeFormat(timeFormat: .military, dateFormat: .dayFirst, dateSeparator: ".", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: ""), message: message, accountPeerId: accountPeerId, forChatList: false) ?? "") } else { return nil } - case let poll as TelegramMediaPoll: + case let .poll(poll): return .poll(poll.text) - case let dice as TelegramMediaDice: + case let .dice(dice): return .dice(dice.emoji) - case let invoice as TelegramMediaInvoice: + case let .invoice(invoice): return .invoice(invoice.title) default: return nil @@ -230,7 +229,7 @@ public func stringForMediaKind(_ kind: MessageContentKind, strings: Presentation } } -public func descriptionStringForMessage(contentSettings: ContentSettings, message: Message, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: PeerId) -> (String, Bool) { +public func descriptionStringForMessage(contentSettings: ContentSettings, message: EngineMessage, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, accountPeerId: EnginePeer.Id) -> (String, Bool) { let contentKind = messageContentKind(contentSettings: contentSettings, message: message, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId) if !message.text.isEmpty && ![.expiredImage, .expiredVideo].contains(contentKind.key) { return (foldLineBreaks(message.text), false) diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 1365862c44..046745e403 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -1,6 +1,5 @@ import Foundation import UIKit -import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -12,11 +11,11 @@ import Markdown private let titleFont = Font.regular(13.0) private let titleBoldFont = Font.bold(13.0) -private func peerMentionAttributes(primaryTextColor: UIColor, peerId: PeerId) -> MarkdownAttributeSet { +private func peerMentionAttributes(primaryTextColor: UIColor, peerId: EnginePeer.Id) -> MarkdownAttributeSet { return MarkdownAttributeSet(font: titleBoldFont, textColor: primaryTextColor, additionalAttributes: [TelegramTextAttributes.PeerMention: TelegramPeerMention(peerId: peerId, mention: "")]) } -private func peerMentionsAttributes(primaryTextColor: UIColor, peerIds: [(Int, PeerId?)]) -> [Int: MarkdownAttributeSet] { +private func peerMentionsAttributes(primaryTextColor: UIColor, peerIds: [(Int, EnginePeer.Id?)]) -> [Int: MarkdownAttributeSet] { var result: [Int: MarkdownAttributeSet] = [:] for (index, peerId) in peerIds { if let peerId = peerId { @@ -26,11 +25,11 @@ private func peerMentionsAttributes(primaryTextColor: UIColor, peerIds: [(Int, P return result } -public func plainServiceMessageString(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, accountPeerId: PeerId, forChatList: Bool) -> String? { +public func plainServiceMessageString(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool) -> String? { return universalServiceMessageString(presentationData: nil, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: forChatList)?.string } -public func universalServiceMessageString(presentationData: (PresentationTheme, TelegramWallpaper)?, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, accountPeerId: PeerId, forChatList: Bool) -> NSAttributedString? { +public func universalServiceMessageString(presentationData: (PresentationTheme, TelegramWallpaper)?, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool) -> NSAttributedString? { var attributedString: NSAttributedString? let primaryTextColor: UIColor @@ -45,7 +44,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, for media in message.media { if let action = media as? TelegramMediaAction { - let authorName = message.author.flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? "" + let authorName = message.author?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? "" var isChannel = false if message.id.peerId.namespace == Namespaces.Peer.CloudChannel, let peer = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = peer.info { @@ -71,7 +70,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, attributedString = addAttributesToStringWithRanges(strings.Notification_JoinedChat(authorName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, peerId)])) } } else { - var attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)] + var attributePeerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)] let resultTitleString: PresentationStrings.FormattedString if peerIds.count == 1 { attributePeerIds.append((1, peerIds.first)) @@ -90,7 +89,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, attributedString = addAttributesToStringWithRanges(strings.Notification_LeftChat(authorName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) } } else { - var attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)] + var attributePeerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)] if peerIds.count == 1 { attributePeerIds.append((1, peerIds.first)) } @@ -153,10 +152,10 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, case deleted } - var pinnedMessage: Message? + var pinnedMessage: EngineMessage? for attribute in message.attributes { if let attribute = attribute as? ReplyMessageAttribute, let message = message.associatedMessages[attribute.messageId] { - pinnedMessage = message + pinnedMessage = EngineMessage(message) } } @@ -263,7 +262,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, case let .messageAutoremoveTimeoutUpdated(timeout): let authorString: String if let author = messageMainPeer(message) { - authorString = EnginePeer(author).compactDisplayTitle + authorString = author.compactDisplayTitle } else { authorString = "" } @@ -325,8 +324,8 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, break case .historyScreenshot: let text: String - if message.effectivelyIncoming(accountPeerId) { - text = strings.Notification_SecretChatMessageScreenshot(message.author.flatMap(EnginePeer.init)?.compactDisplayTitle ?? "").string + if message._asMessage().effectivelyIncoming(accountPeerId) { + text = strings.Notification_SecretChatMessageScreenshot(message.author?.compactDisplayTitle ?? "").string } else { text = strings.Notification_SecretChatMessageScreenshotSelf } @@ -372,10 +371,10 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, argumentAttributes[1] = MarkdownAttributeSet(font: titleBoldFont, textColor: primaryTextColor, additionalAttributes: [:]) attributedString = addAttributesToStringWithRanges(formatWithArgumentRanges(baseString, ranges, [authorName, gameTitle ?? ""]), body: bodyAttributes, argumentAttributes: argumentAttributes) case let .paymentSent(currency, totalAmount): - var invoiceMessage: Message? + var invoiceMessage: EngineMessage? for attribute in message.attributes { if let attribute = attribute as? ReplyMessageAttribute, let message = message.associatedMessages[attribute.messageId] { - invoiceMessage = message + invoiceMessage = EngineMessage(message) } } @@ -391,7 +390,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, if let invoiceTitle = invoiceTitle { let botString: String if let peer = messageMainPeer(message) { - botString = EnginePeer(peer).compactDisplayTitle + botString = peer.compactDisplayTitle } else { botString = "" } @@ -441,7 +440,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, if let scheduleDate = scheduleDate { if message.author?.id.namespace == Namespaces.Peer.CloudChannel { let titleString: PresentationStrings.FormattedString - if let channel = message.author as? TelegramChannel, case .broadcast = channel.info { + if case let .channel(channel) = message.author, case .broadcast = channel.info { titleString = humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: scheduleDate, alwaysShowTime: true, allowYesterday: false, format: HumanReadableStringFormat(dateFormatString: { strings.Notification_LiveStreamScheduled($0) }, tomorrowFormatString: { strings.Notification_LiveStreamScheduledTomorrow($0) }, todayFormatString: { strings.Notification_LiveStreamScheduledToday($0) })) } else { titleString = humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: scheduleDate, alwaysShowTime: true, allowYesterday: false, format: HumanReadableStringFormat(dateFormatString: { strings.Notification_VoiceChatScheduledChannel($0) }, tomorrowFormatString: { strings.Notification_VoiceChatScheduledTomorrowChannel($0) }, todayFormatString: { strings.Notification_VoiceChatScheduledTodayChannel($0) })) @@ -449,34 +448,34 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, attributedString = NSAttributedString(string: titleString.string, font: titleFont, textColor: primaryTextColor) } else { let titleString = humanReadableStringForTimestamp(strings: strings, dateTimeFormat: dateTimeFormat, timestamp: scheduleDate, alwaysShowTime: true, allowYesterday: false, format: HumanReadableStringFormat(dateFormatString: { strings.Notification_VoiceChatScheduled(authorName, $0) }, tomorrowFormatString: { strings.Notification_VoiceChatScheduledTomorrow(authorName, $0) }, todayFormatString: { strings.Notification_VoiceChatScheduledToday(authorName, $0) })) - let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)] + let attributePeerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)] attributedString = addAttributesToStringWithRanges(titleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds)) } } else if let duration = duration { if message.author?.id.namespace == Namespaces.Peer.CloudChannel { let titleString: String - if let channel = message.author as? TelegramChannel, case .broadcast = channel.info { + if case let .channel(channel) = message.author, case .broadcast = channel.info { titleString = strings.Notification_LiveStreamEnded(callDurationString(strings: strings, value: duration)).string } else { titleString = strings.Notification_VoiceChatEnded(callDurationString(strings: strings, value: duration)).string } attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor) } else { - let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)] + let attributePeerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)] let titleString = strings.Notification_VoiceChatEndedGroup(authorName, callDurationString(strings: strings, value: duration)) attributedString = addAttributesToStringWithRanges(titleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds)) } } else { if message.author?.id.namespace == Namespaces.Peer.CloudChannel { let titleString: String - if let channel = message.author as? TelegramChannel, case .broadcast = channel.info { + if case let .channel(channel) = message.author, case .broadcast = channel.info { titleString = strings.Notification_LiveStreamStarted } else { titleString = strings.Notification_VoiceChatStartedChannel } attributedString = NSAttributedString(string: titleString, font: titleFont, textColor: primaryTextColor) } else { - let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)] + let attributePeerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)] let titleString = strings.Notification_VoiceChatStarted(authorName) attributedString = addAttributesToStringWithRanges(titleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds)) } @@ -529,7 +528,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, attributedString = addAttributesToStringWithRanges(strings.Notification_ProximityReached(message.peers[fromId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? "", distanceString, message.peers[toId].flatMap(EnginePeer.init)?.displayTitle(strings: strings, displayOrder: nameDisplayOrder) ?? "")._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, fromId), (2, toId)])) } case let .inviteToGroupPhoneCall(_, _, peerIds): - var attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)] + var attributePeerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)] let resultTitleString: PresentationStrings.FormattedString if peerIds.count == 1 { if peerIds[0] == accountPeerId { @@ -551,7 +550,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, } else if message.author?.id == accountPeerId { attributedString = NSAttributedString(string: strings.Notification_YouDisabledTheme, font: titleFont, textColor: primaryTextColor) } else { - let attributePeerIds: [(Int, PeerId?)] = [(0, message.author?.id)] + let attributePeerIds: [(Int, EnginePeer.Id?)] = [(0, message.author?.id)] let resultTitleString = strings.Notification_DisabledTheme(authorName) attributedString = addAttributesToStringWithRanges(resultTitleString._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: attributePeerIds)) } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index ed1c70045c..0fceea4376 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -188,7 +188,6 @@ swift_library( "//submodules/WatchBridge:WatchBridge", "//submodules/ShareItems:ShareItems", "//submodules/ShareItems/Impl:ShareItemsImpl", - "//submodules/ReactionSelectionNode:ReactionSelectionNode", "//submodules/SettingsUI:SettingsUI", "//submodules/UrlHandling:UrlHandling", "//submodules/HexColor:HexColor", diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index c560854080..7039e7ea97 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -44,7 +44,6 @@ import PeerAvatarGalleryUI import PeerInfoUI import RaiseToListen import UrlHandling -import ReactionSelectionNode import AvatarNode import AppBundle import LocalizedPeerData @@ -934,35 +933,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self, !actions.items.isEmpty else { return } - var reactionItems: [ReactionContextItem] = [] - - /*var hasLike = false - let hearts: [String] = ["❤", "❤️"] - for attribute in messages[0].attributes { - if let attribute = attribute as? ReactionsMessageAttribute { - for reaction in attribute.reactions { - if hearts.contains(reaction.value) { - if reaction.isSelected { - hasLike = true - } - } - } - } else if let attribute = attribute as? PendingReactionsMessageAttribute { - if let value = attribute.value, hearts.contains(value) { - hasLike = true - } - } - } - - if hasLike { - reactionItems.append(ReactionContextItem(reaction: .unlike)) - } else { - reactionItems.append(ReactionContextItem(reaction: .like)) - }*/ - - if Namespaces.Message.allScheduled.contains(message.id.namespace) || message.id.peerId.namespace == Namespaces.Peer.SecretChat { - reactionItems = [] - } var tip: ContextController.Tip? @@ -979,47 +949,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G actions.tip = tip } - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, selectAll: selectAll)), items: .single(actions), reactionItems: reactionItems, recognizer: recognizer, gesture: gesture) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, selectAll: selectAll)), items: .single(actions), recognizer: recognizer, gesture: gesture) strongSelf.currentContextController = controller - controller.reactionSelected = { [weak controller] value in - guard let strongSelf = self, let message = updatedMessages.first else { - return - } - let hearts: [String] = ["❤", "❤️"] - strongSelf.chatDisplayNode.historyNode.forEachItemNode { itemNode in - if let itemNode = itemNode as? ChatMessageItemView, let item = itemNode.item { - if item.message.id == message.id { - switch value { - case .like: - itemNode.awaitingAppliedReaction = (hearts[0], { [weak itemNode] in - guard let controller = controller else { - return - } - if let itemNode = itemNode, let (targetEmptyNode, targetFilledNode) = itemNode.targetReactionNode(value: hearts[0]) { - controller.dismissWithReaction(value: hearts[0], targetEmptyNode: targetEmptyNode, targetFilledNode: targetFilledNode, hideNode: true, completion: { - }) - } else { - controller.dismiss() - } - }) - case .unlike: - itemNode.awaitingAppliedReaction = (nil, { - guard let controller = controller else { - return - } - controller.dismiss() - }) - } - } - } - } - switch value { - case .like: - let _ = updateMessageReactionsInteractively(postbox: strongSelf.context.account.postbox, messageId: message.id, reaction: hearts[0]).start() - case .unlike: - let _ = updateMessageReactionsInteractively(postbox: strongSelf.context.account.postbox, messageId: message.id, reaction: nil).start() - } - } + strongSelf.forEachController({ controller in if let controller = controller as? TooltipScreen { controller.dismiss() @@ -1734,8 +1666,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return self?.navigationController as? NavigationController }, chatControllerNode: { [weak self] in return self?.chatDisplayNode - }, reactionContainerNode: { [weak self] in - return self?.chatDisplayNode.reactionContainerNode }, presentGlobalOverlayController: { [weak self] controller, arguments in self?.presentInGlobalOverlay(controller, with: arguments) }, callPeer: { [weak self] peerId, isVideo in @@ -2162,28 +2092,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if canReplyInChat(strongSelf.presentationInterfaceState) { return .reply } else if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .broadcast = channel.info { - /*var hasLike = false - let hearts: [String] = ["❤", "❤️"] - for attribute in message.attributes { - if let attribute = attribute as? ReactionsMessageAttribute { - for reaction in attribute.reactions { - if hearts.contains(reaction.value) { - if reaction.isSelected { - hasLike = true - } - } - } - } else if let attribute = attribute as? PendingReactionsMessageAttribute { - if let value = attribute.value, hearts.contains(value) { - hasLike = true - } - } - } - if hasLike { - return .unlike - } else { - return .like - }*/ } } return .none @@ -2235,7 +2143,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }))) - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, selectAll: true)), items: .single(ContextController.Items(items: actions)), reactionItems: [], recognizer: nil) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: message, selectAll: true)), items: .single(ContextController.Items(items: actions)), recognizer: nil) strongSelf.currentContextController = controller strongSelf.forEachController({ controller in if let controller = controller as? TooltipScreen { @@ -2312,7 +2220,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G f(.dismissWithoutContent) }))) - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: topMessage, selectAll: true)), items: .single(ContextController.Items(items: actions)), reactionItems: [], recognizer: nil) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(ChatMessageContextExtractedContentSource(chatNode: strongSelf.chatDisplayNode, postbox: strongSelf.context.account.postbox, message: topMessage, selectAll: true)), items: .single(ContextController.Items(items: actions)), recognizer: nil) strongSelf.currentContextController = controller strongSelf.forEachController({ controller in if let controller = controller as? TooltipScreen { @@ -2604,18 +2512,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G case .speak: speakText(text.string) } - }, updateMessageLike: { [weak self] messageId, isLiked in - guard let strongSelf = self else { - return - } - - let heart = "❤" - if isLiked { - let _ = updateMessageReactionsInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, reaction: heart).start() - } else { - let _ = updateMessageReactionsInteractively(postbox: strongSelf.context.account.postbox, messageId: messageId, reaction: nil).start() - } - }, openMessageReactions: { _ in }, displayImportedMessageTooltip: { [weak self] _ in guard let strongSelf = self else { return @@ -2755,7 +2651,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return items } - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node, passthroughTouches: false)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node, passthroughTouches: false)), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) }) }, openMessageReplies: { [weak self] messageId, isChannelPost, displayModalProgress in @@ -3034,7 +2930,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return items } - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node, passthroughTouches: false)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node, passthroughTouches: false)), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) } chatInfoButtonItem = UIBarButtonItem(customDisplayNode: avatarNode)! @@ -5841,7 +5737,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return items } - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: sourceNode, passthroughTouches: true)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: []) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: sourceNode, passthroughTouches: true)), items: items |> map { ContextController.Items(items: $0) }) contextController.dismissedForCancel = { [weak chatController] in if let selectedMessageIds = (chatController as? ChatControllerImpl)?.selectedMessageIds { var forwardMessageIds = strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [] @@ -7349,7 +7245,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peerId), subject: .pinnedMessages(id: pinnedMessage.message.id), botStart: nil, mode: .standard(previewing: true)) chatController.canReadHistory.set(false) - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, passthroughTouches: true)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, passthroughTouches: true)), items: .single(ContextController.Items(items: items)), gesture: gesture) strongSelf.presentInGlobalOverlay(contextController) }, joinGroupCall: { [weak self] activeCall in guard let strongSelf = self, let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer else { diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index d5836f9602..838237d59b 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -8,7 +8,6 @@ import Display import TelegramUIPreferences import AccountContext import TextSelectionNode -import ReactionSelectionNode import ContextUI import ChatInterfaceState import UndoUI @@ -45,8 +44,6 @@ struct ChatInterfacePollActionState: Equatable { public enum ChatControllerInteractionSwipeAction { case none case reply - case like - case unlike } public final class ChatControllerInteraction { @@ -83,7 +80,6 @@ public final class ChatControllerInteraction { let presentController: (ViewController, Any?) -> Void let navigationController: () -> NavigationController? let chatControllerNode: () -> ASDisplayNode? - let reactionContainerNode: () -> ReactionSelectionParentNode? let presentGlobalOverlayController: (ViewController, Any?) -> Void let callPeer: (PeerId, Bool) -> Void let longTap: (ChatControllerInteractionLongTapAction, Message?) -> Void @@ -104,8 +100,6 @@ public final class ChatControllerInteraction { let sendScheduledMessagesNow: ([MessageId]) -> Void let editScheduledMessagesTime: ([MessageId]) -> Void let performTextSelectionAction: (UInt32, NSAttributedString, TextSelectionAction) -> Void - let updateMessageLike: (MessageId, Bool) -> Void - let openMessageReactions: (MessageId) -> Void let displayImportedMessageTooltip: (ASDisplayNode) -> Void let displaySwipeToReplyHint: () -> Void let dismissReplyMarkupMessage: (Message) -> Void @@ -180,7 +174,6 @@ public final class ChatControllerInteraction { presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, - reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId, Bool) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, @@ -201,8 +194,6 @@ public final class ChatControllerInteraction { sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, NSAttributedString, TextSelectionAction) -> Void, - updateMessageLike: @escaping (MessageId, Bool) -> Void, - openMessageReactions: @escaping (MessageId) -> Void, displayImportedMessageTooltip: @escaping (ASDisplayNode) -> Void, displaySwipeToReplyHint: @escaping () -> Void, dismissReplyMarkupMessage: @escaping (Message) -> Void, @@ -263,7 +254,6 @@ public final class ChatControllerInteraction { self.presentController = presentController self.navigationController = navigationController self.chatControllerNode = chatControllerNode - self.reactionContainerNode = reactionContainerNode self.presentGlobalOverlayController = presentGlobalOverlayController self.callPeer = callPeer self.longTap = longTap @@ -287,8 +277,6 @@ public final class ChatControllerInteraction { self.sendScheduledMessagesNow = sendScheduledMessagesNow self.editScheduledMessagesTime = editScheduledMessagesTime self.performTextSelectionAction = performTextSelectionAction - self.updateMessageLike = updateMessageLike - self.openMessageReactions = openMessageReactions self.displayImportedMessageTooltip = displayImportedMessageTooltip self.displaySwipeToReplyHint = displaySwipeToReplyHint self.dismissReplyMarkupMessage = dismissReplyMarkupMessage @@ -324,8 +312,6 @@ public final class ChatControllerInteraction { return nil }, chatControllerNode: { return nil - }, reactionContainerNode: { - return nil }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in }, canSetupReply: { _ in return .none @@ -342,8 +328,6 @@ public final class ChatControllerInteraction { }, sendScheduledMessagesNow: { _ in }, editScheduledMessagesTime: { _ in }, performTextSelectionAction: { _, _, _ in - }, updateMessageLike: { _, _ in - }, openMessageReactions: { _ in }, displayImportedMessageTooltip: { _ in }, displaySwipeToReplyHint: { }, dismissReplyMarkupMessage: { _ in diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 876092e5f6..4ae7c5aa92 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -10,7 +10,6 @@ import TelegramUIPreferences import TextFormat import AccountContext import TelegramNotices -import ReactionSelectionNode import TelegramUniversalVideoContent import ChatInterfaceState import FastBlur @@ -83,7 +82,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let backgroundNode: WallpaperBackgroundNode let historyNode: ChatHistoryListNode var blurredHistoryNode: ASImageNode? - let reactionContainerNode: ReactionSelectionParentNode let historyNodeContainer: ASDisplayNode let loadingNode: ChatLoadingNode private var emptyNode: ChatEmptyNode? @@ -336,8 +334,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { onTransitionEventImpl?(transition) }) - self.reactionContainerNode = ReactionSelectionParentNode(account: context.account, theme: chatPresentationInterfaceState.theme) - self.loadingNode = ChatLoadingNode(theme: self.chatPresentationInterfaceState.theme, chatWallpaper: self.chatPresentationInterfaceState.chatWallpaper, bubbleCorners: self.chatPresentationInterfaceState.bubbleCorners) if case let .color(color) = self.chatPresentationInterfaceState.chatWallpaper, UIColor(rgb: color).isEqual(self.chatPresentationInterfaceState.theme.chat.inputPanel.panelBackgroundColorNoWallpaper) { @@ -1178,9 +1174,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { transition.updateFrame(node: emptyNode, frame: contentBounds) } - transition.updateFrame(node: self.reactionContainerNode, frame: contentBounds) - self.reactionContainerNode.updateLayout(size: contentBounds.size, insets: UIEdgeInsets(), transition: transition) - var contentBottomInset: CGFloat = inputPanelsHeight + 4.0 if let scrollContainerNode = self.scrollContainerNode { @@ -1852,10 +1845,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } else { completion(.immediate) } - - if self.reactionContainerNode.supernode == nil { - self.addSubnode(self.reactionContainerNode) - } } func updateAutomaticMediaDownloadSettings(_ settings: MediaAutoDownloadSettings) { diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index f3473e49d1..8d2720b91f 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -470,7 +470,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { private let messageProcessingManager = ChatMessageThrottledProcessingManager() private let adSeenProcessingManager = ChatMessageThrottledProcessingManager() - private let messageReactionsProcessingManager = ChatMessageThrottledProcessingManager() private let seenLiveLocationProcessingManager = ChatMessageThrottledProcessingManager() private let unsupportedMessageProcessingManager = ChatMessageThrottledProcessingManager() private let refreshMediaProcessingManager = ChatMessageThrottledProcessingManager() @@ -631,9 +630,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } } } - self.messageReactionsProcessingManager.process = { [weak context] messageIds in - context?.account.viewTracker.updateReactionsForMessageIds(messageIds: messageIds) - } self.seenLiveLocationProcessingManager.process = { [weak context] messageIds in context?.account.viewTracker.updateSeenLiveLocationForMessageIds(messageIds: messageIds) } @@ -1503,7 +1499,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { var messageIdsWithViewCount: [MessageId] = [] var messageIdsWithAds: [MessageId] = [] - var messageIdsWithUpdateableReactions: [MessageId] = [] var messageIdsWithLiveLocation: [MessageId] = [] var messageIdsWithUnsupportedMedia: [MessageId] = [] var messageIdsWithRefreshMedia: [MessageId] = [] @@ -1541,7 +1536,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { contentRequiredValidation = true } } - var isAction = false for media in message.media { if let _ = media as? TelegramMediaUnsupported { contentRequiredValidation = true @@ -1550,8 +1544,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { if message.timestamp + liveBroadcastingTimeout > timestamp { messageIdsWithLiveLocation.append(message.id) } - } else if let _ = media as? TelegramMediaAction { - isAction = true } else if let telegramFile = media as? TelegramMediaFile { if telegramFile.isAnimatedSticker, (message.id.peerId.namespace == Namespaces.Peer.SecretChat || !telegramFile.previewRepresentations.isEmpty), let size = telegramFile.size, size > 0 && size <= 128 * 1024 { if message.id.peerId.namespace == Namespaces.Peer.SecretChat { @@ -1572,9 +1564,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } } } - if !isAction && message.id.peerId.namespace == Namespaces.Peer.CloudChannel { - messageIdsWithUpdateableReactions.append(message.id) - } if contentRequiredValidation { messageIdsWithUnsupportedMedia.append(message.id) } @@ -1703,9 +1692,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { if !messageIdsWithAds.isEmpty { self.adSeenProcessingManager.add(messageIdsWithAds) } - if !messageIdsWithUpdateableReactions.isEmpty { - self.messageReactionsProcessingManager.add(messageIdsWithUpdateableReactions) - } if !messageIdsWithLiveLocation.isEmpty { self.seenLiveLocationProcessingManager.add(messageIdsWithLiveLocation) } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index b07064aaf4..0363e076a6 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -1465,7 +1465,7 @@ final class ChatMediaInputNode: ChatInputNode { let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceNode: sourceNode, sourceRect: sourceRect)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceNode: sourceNode, sourceRect: sourceRect)), items: .single(ContextController.Items(items: items)), gesture: gesture) strongSelf.controllerInteraction.presentGlobalOverlayController(contextController, nil) }) } diff --git a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift index 3fa59cf22c..0559c304d1 100644 --- a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift @@ -19,7 +19,7 @@ import GalleryUI import WallpaperBackgroundNode private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, accountPeerId: PeerId) -> NSAttributedString? { - return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: false) + return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), accountPeerId: accountPeerId, forChatList: false) } class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 2ae27e7385..9170a47ab6 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -299,13 +299,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { self.messageAccessibilityArea.focused = { [weak self] in self?.accessibilityElementDidBecomeFocused() } - - self.dateAndStatusNode.openReactions = { [weak self] in - guard let strongSelf = self, let item = strongSelf.item else { - return - } - item.controllerInteraction.openMessageReactions(item.message.id) - } } deinit { @@ -352,7 +345,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { guard let strongSelf = self else { return } - //strongSelf.reactionRecognizer?.cancel() + if let action = strongSelf.gestureRecognized(gesture: .longTap, location: point, recognizer: recognizer) { switch action { case let .action(f): @@ -875,27 +868,14 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular) var isReplyThread = false if case .replyThread = item.chatLocation { isReplyThread = true } - let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), dateReactions, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) + let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) var viaBotApply: (TextNodeLayout, () -> TextNode)? var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)? @@ -1836,10 +1816,6 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { break case .reply: item.controllerInteraction.setupReply(item.message.id) - case .like: - item.controllerInteraction.updateMessageLike(item.message.id, true) - case .unlike: - item.controllerInteraction.updateMessageLike(item.message.id, true) } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift index f4cc8e02f3..464453b54c 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift @@ -329,20 +329,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - - let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings) var webpageGalleryMediaCount: Int? for media in message.media { @@ -506,7 +493,6 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { edited: edited, viewCount: viewCount, dateReplies: dateReplies, - dateReactions: dateReactions, isPinned: message.tags.contains(.pinned) && !associatedData.isInPinnedListMode && !isReplyThread, dateText: dateText ) @@ -626,7 +612,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { let textConstrainedSize = CGSize(width: constrainedSize.width - insets.left - insets.right, height: constrainedSize.height - insets.top - insets.bottom) if let textStatusType = textStatusType { - statusSizeAndApply = statusLayout(context, presentationData, edited, viewCount, dateText, textStatusType, textConstrainedSize, dateReactions, dateReplies, message.tags.contains(.pinned) && !associatedData.isInPinnedListMode && !isReplyThread, message.isSelfExpiring) + statusSizeAndApply = statusLayout(context, presentationData, edited, viewCount, dateText, textStatusType, textConstrainedSize, dateReplies, message.tags.contains(.pinned) && !associatedData.isInPinnedListMode && !isReplyThread, message.isSelfExpiring) } var updatedAdditionalImageBadge: ChatMessageInteractiveMediaBadge? @@ -1120,11 +1106,4 @@ final class ChatMessageAttachedContentNode: ASDisplayNode { func playMediaWithSound() -> ((Double?) -> Void, Bool, Bool, Bool, ASDisplayNode?)? { return self.contentImageNode?.playMediaWithSound() } - - func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - if !self.statusNode.isHidden { - return self.statusNode.reactionNode(value: value) - } - return nil - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleContentNode.swift index 01a062a262..db3775ce12 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleContentNode.swift @@ -210,10 +210,6 @@ class ChatMessageBubbleContentNode: ASDisplayNode { func applyAbsoluteOffsetSpring(value: CGFloat, duration: Double, damping: CGFloat) { } - func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - return nil - } - func getStatusNode() -> ASDisplayNode? { return nil } diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index c195435489..f077acfc5f 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -16,7 +16,6 @@ import MosaicLayout import TextSelectionNode import PlatformRestrictionMatching import Emoji -import ReactionSelectionNode import PersistentStringHash import GridMessageSelectionNode import AppBundle @@ -438,7 +437,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode private var appliedForwardInfo: (Peer?, String?)? private var tapRecognizer: TapLongTapOrDoubleTapGestureRecognizer? - private var reactionRecognizer: ReactionSwipeGestureRecognizer? private var currentSwipeAction: ChatControllerInteractionSwipeAction? @@ -799,7 +797,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode guard let strongSelf = self else { return } - strongSelf.reactionRecognizer?.cancel() + if let action = strongSelf.gestureRecognized(gesture: .longTap, location: point, recognizer: recognizer) { switch action { case let .action(f): @@ -828,234 +826,35 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode self.tapRecognizer = recognizer self.view.addGestureRecognizer(recognizer) self.view.isExclusiveTouch = true - - if true { - let replyRecognizer = ChatSwipeToReplyRecognizer(target: self, action: #selector(self.swipeToReplyGesture(_:))) - replyRecognizer.shouldBegin = { [weak self] in - if let strongSelf = self, let item = strongSelf.item { - if strongSelf.selectionNode != nil { - return false - } - for media in item.content.firstMessage.media { - if let _ = media as? TelegramMediaExpiredContent { - return false - } - else if let media = media as? TelegramMediaAction { - if case .phoneCall(_, _, _, _) = media.action { - } else { - return false - } - } - } - let action = item.controllerInteraction.canSetupReply(item.message) - strongSelf.currentSwipeAction = action - if case .none = action { - return false - } else { - return true - } - } - return false - } - self.view.addGestureRecognizer(replyRecognizer) - } else { - /*let reactionRecognizer = ReactionSwipeGestureRecognizer(target: nil, action: nil) - self.reactionRecognizer = reactionRecognizer - reactionRecognizer.availableReactions = { [weak self] in - guard let strongSelf = self, let item = strongSelf.item, !item.presentationData.isPreview && !Namespaces.Message.allScheduled.contains(item.message.id.namespace) else { - return [] - } + + let replyRecognizer = ChatSwipeToReplyRecognizer(target: self, action: #selector(self.swipeToReplyGesture(_:))) + replyRecognizer.shouldBegin = { [weak self] in + if let strongSelf = self, let item = strongSelf.item { if strongSelf.selectionNode != nil { - return [] + return false } for media in item.content.firstMessage.media { if let _ = media as? TelegramMediaExpiredContent { - return [] + return false } else if let media = media as? TelegramMediaAction { - if case .phoneCall = media.action { + if case .phoneCall(_, _, _, _) = media.action { } else { - return [] + return false } } } - - let reactions: [(String, String, String)] = [ - ("😔", "Sad", "sad"), - ("😳", "Surprised", "surprised"), - ("😂", "Fun", "lol"), - ("👍", "Like", "thumbsup"), - ("❤", "Love", "heart"), - ] - - var reactionItems: [ReactionGestureItem] = [] - for (value, text, name) in reactions.reversed() { - if let path = getAppBundle().path(forResource: name, ofType: "tgs") { - reactionItems.append(.reaction(value: value, text: text, path: path)) - } - } - if item.controllerInteraction.canSetupReply(item.message) { - //reactionItems.append(.reply) - } - return reactionItems - } - reactionRecognizer.getReactionContainer = { [weak self] in - return self?.item?.controllerInteraction.reactionContainerNode() - } - reactionRecognizer.getAnchorPoint = { [weak self] in - guard let strongSelf = self else { - return nil - } - return CGPoint(x: strongSelf.backgroundNode.frame.maxX, y: strongSelf.backgroundNode.frame.minY) - } - reactionRecognizer.shouldElevateAnchorPoint = { [weak self] in - guard let strongSelf = self, let item = strongSelf.item else { + let action = item.controllerInteraction.canSetupReply(item.message) + strongSelf.currentSwipeAction = action + if case .none = action { return false - } - return item.controllerInteraction.canSetupReply(item.message) - } - reactionRecognizer.began = { [weak self] in - guard let strongSelf = self, let item = strongSelf.item else { - return - } - item.controllerInteraction.cancelInteractiveKeyboardGestures() - } - reactionRecognizer.updateOffset = { [weak self] offset, animated in - guard let strongSelf = self else { - return - } - var bounds = strongSelf.bounds - bounds.origin.x = offset - strongSelf.bounds = bounds - - var shadowBounds = strongSelf.shadowNode.bounds - shadowBounds.origin.x = offset - strongSelf.shadowNode.bounds = shadowBounds - - if animated { - strongSelf.layer.animateBoundsOriginXAdditive(from: -offset, to: 0.0, duration: 0.1, mediaTimingFunction: CAMediaTimingFunction(name: .easeOut)) - strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: -offset, to: 0.0, duration: 0.1, mediaTimingFunction: CAMediaTimingFunction(name: .easeOut)) - } - if let swipeToReplyNode = strongSelf.swipeToReplyNode { - swipeToReplyNode.alpha = max(0.0, min(1.0, abs(offset / 40.0))) - } - } - reactionRecognizer.activateReply = { [weak self] in - guard let strongSelf = self, let item = strongSelf.item else { - return - } - var bounds = strongSelf.bounds - let offset = bounds.origin.x - bounds.origin.x = 0.0 - strongSelf.bounds = bounds - - var shadowBounds = strongSelf.shadowNode.bounds - let shadowOffset = shadowBounds.origin.x - shadowBounds.origin.x = 0.0 - strongSelf.shadowNode.bounds = shadowBounds - - if !offset.isZero { - strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) - } - if !shadowOffset.isZero { - strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: shadowOffset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) - } - if let swipeToReplyNode = strongSelf.swipeToReplyNode { - strongSelf.swipeToReplyNode = nil - swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in - swipeToReplyNode?.removeFromSupernode() - }) - swipeToReplyNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) - } - item.controllerInteraction.setupReply(item.message.id) - } - reactionRecognizer.displayReply = { [weak self] offset in - guard let strongSelf = self, let item = strongSelf.item else { - return - } - if !item.controllerInteraction.canSetupReply(item.message) { - return - } - if strongSelf.swipeToReplyFeedback == nil { - strongSelf.swipeToReplyFeedback = HapticFeedback() - } - strongSelf.swipeToReplyFeedback?.tap() - if strongSelf.swipeToReplyNode == nil { - let swipeToReplyNode = ChatMessageSwipeToReplyNode(fillColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonFillColor, wallpaper: item.presentationData.theme.wallpaper), strokeColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonStrokeColor, wallpaper: item.presentationData.theme.wallpaper), foregroundColor: bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.shareButtonForegroundColor, wallpaper: item.presentationData.theme.wallpaper)) - strongSelf.swipeToReplyNode = swipeToReplyNode - strongSelf.insertSubnode(swipeToReplyNode, belowSubnode: strongSelf.messageAccessibilityArea) - swipeToReplyNode.frame = CGRect(origin: CGPoint(x: strongSelf.bounds.size.width, y: floor((strongSelf.contentSize.height - 33.0) / 2.0)), size: CGSize(width: 33.0, height: 33.0)) - swipeToReplyNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.12) - swipeToReplyNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.4) - } - } - reactionRecognizer.completed = { [weak self] reaction in - guard let strongSelf = self else { - return - } - if let item = strongSelf.item, let reaction = reaction { - switch reaction { - case let .reaction(value, _, _): - var resolvedValue: String? - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), reactionsAttribute.reactions.contains(where: { $0.value == value }) { - resolvedValue = nil - } else { - resolvedValue = value - } - strongSelf.awaitingAppliedReaction = (resolvedValue, {}) - item.controllerInteraction.updateMessageReaction(item.message.id, resolvedValue) - case .reply: - strongSelf.reactionRecognizer?.complete(into: nil, hideTarget: false) - var bounds = strongSelf.bounds - let offset = bounds.origin.x - bounds.origin.x = 0.0 - strongSelf.bounds = bounds - var shadowBounds = strongSelf.shadowNode.bounds - let shadowOffset = shadowBounds.origin.x - shadowBounds.origin.x = 0.0 - strongSelf.shadowNode.bounds = shadowBounds - if !offset.isZero { - strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) - } - if !shadowOffset.isZero { - strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: shadowOffset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) - } - if let swipeToReplyNode = strongSelf.swipeToReplyNode { - strongSelf.swipeToReplyNode = nil - swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in - swipeToReplyNode?.removeFromSupernode() - }) - swipeToReplyNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) - } - item.controllerInteraction.setupReply(item.message.id) - } } else { - strongSelf.reactionRecognizer?.complete(into: nil, hideTarget: false) - var bounds = strongSelf.bounds - let offset = bounds.origin.x - bounds.origin.x = 0.0 - strongSelf.bounds = bounds - var shadowBounds = strongSelf.shadowNode.bounds - let shadowOffset = shadowBounds.origin.x - shadowBounds.origin.x = 0.0 - strongSelf.shadowNode.bounds = shadowBounds - if !offset.isZero { - strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) - } - if !shadowOffset.isZero { - strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: shadowOffset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) - } - if let swipeToReplyNode = strongSelf.swipeToReplyNode { - strongSelf.swipeToReplyNode = nil - swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in - swipeToReplyNode?.removeFromSupernode() - }) - swipeToReplyNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) - } + return true } } - self.view.addGestureRecognizer(reactionRecognizer)*/ + return false } + self.view.addGestureRecognizer(replyRecognizer) } override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, ListViewItemApply, Bool) -> Void) { @@ -1110,7 +909,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode forwardInfoLayout: (ChatPresentationData, PresentationStrings, ChatMessageForwardInfoType, Peer?, String?, String?, CGSize) -> (CGSize, (CGFloat) -> ChatMessageForwardInfoNode), replyInfoLayout: (ChatPresentationData, PresentationStrings, AccountContext, ChatMessageReplyInfoType, Message, CGSize) -> (CGSize, () -> ChatMessageReplyInfoNode), actionButtonsLayout: (AccountContext, ChatPresentationThemeData, PresentationChatBubbleCorners, PresentationStrings, ReplyMarkupMessageAttribute, Message, CGFloat) -> (minWidth: CGFloat, layout: (CGFloat) -> (CGSize, (Bool) -> ChatMessageActionButtonsNode)), - mosaicStatusLayout: (AccountContext, ChatPresentationData, Bool, Int?, String, ChatMessageDateAndStatusType, CGSize, [MessageReaction], Int, Bool, Bool) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode), + mosaicStatusLayout: (AccountContext, ChatPresentationData, Bool, Int?, String, ChatMessageDateAndStatusType, CGSize, Int, Bool, Bool) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode), layoutConstants: ChatMessageItemLayoutConstants, currentItem: ChatMessageItem?, currentForwardInfo: (Peer?, String?)?, @@ -1678,26 +1477,13 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - let dateFormat: MessageTimestampStatusFormat if let subject = item.associatedData.subject, case .forwardedMessages = subject { dateFormat = .minimal } else { dateFormat = .regular } - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: dateFormat, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: dateFormat) let statusType: ChatMessageDateAndStatusType if message.effectivelyIncoming(item.context.account.peerId) { @@ -1717,7 +1503,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode isReplyThread = true } - mosaicStatusSizeAndApply = mosaicStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: 200.0, height: CGFloat.greatestFiniteMagnitude), dateReactions, dateReplies, message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, message.isSelfExpiring) + mosaicStatusSizeAndApply = mosaicStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: 200.0, height: CGFloat.greatestFiniteMagnitude), dateReplies, message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, message.isSelfExpiring) } } @@ -2889,45 +2675,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode } strongSelf.updateSearchTextHighlightState() - - /*if let (awaitingAppliedReaction, f) = strongSelf.awaitingAppliedReaction { - var bounds = strongSelf.bounds - let offset = bounds.origin.x - bounds.origin.x = 0.0 - strongSelf.bounds = bounds - var shadowBounds = strongSelf.shadowNode.bounds - let shadowOffset = shadowBounds.origin.x - shadowBounds.origin.x = 0.0 - strongSelf.shadowNode.bounds = shadowBounds - if !offset.isZero { - strongSelf.layer.animateBoundsOriginXAdditive(from: offset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) - } - if !shadowOffset.isZero { - strongSelf.shadowNode.layer.animateBoundsOriginXAdditive(from: shadowOffset, to: 0.0, duration: 0.2, timingFunction: kCAMediaTimingFunctionSpring) - } - if let swipeToReplyNode = strongSelf.swipeToReplyNode { - strongSelf.swipeToReplyNode = nil - swipeToReplyNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak swipeToReplyNode] _ in - swipeToReplyNode?.removeFromSupernode() - }) - swipeToReplyNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false) - } - - strongSelf.awaitingAppliedReaction = nil - /*var targetNode: ASDisplayNode? - var hideTarget = false - if let awaitingAppliedReaction = awaitingAppliedReaction { - for contentNode in strongSelf.contentNodes { - if let (reactionNode, count) = contentNode.reactionTargetNode(value: awaitingAppliedReaction) { - targetNode = reactionNode - hideTarget = count == 1 - break - } - } - } - strongSelf.reactionRecognizer?.complete(into: targetNode, hideTarget: hideTarget)*/ - f() - }*/ } override func updateAccessibilityData(_ accessibilityData: ChatMessageAccessibilityData) { @@ -3766,10 +3513,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode break case .reply: item.controllerInteraction.setupReply(item.message.id) - case .like: - item.controllerInteraction.updateMessageLike(item.message.id, true) - case .unlike: - item.controllerInteraction.updateMessageLike(item.message.id, false) } } } @@ -3854,15 +3597,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode self.mainContextSourceNode.contentNode.addSubnode(accessoryItemNode) } - override func targetReactionNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - for contentNode in self.contentNodes { - if let (emptyNode, filledNode) = contentNode.reactionTargetNode(value: value) { - return (emptyNode, filledNode) - } - } - return nil - } - private var backgroundMaskMode: Bool { let hasWallpaper = self.item?.presentationData.theme.wallpaper.hasWallpaper ?? false let isPreview = self.item?.presentationData.isPreview ?? false diff --git a/submodules/TelegramUI/Sources/ChatMessageCallBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageCallBubbleContentNode.swift index b1dc6ef568..c14d04ee1a 100644 --- a/submodules/TelegramUI/Sources/ChatMessageCallBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageCallBubbleContentNode.swift @@ -167,7 +167,7 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode { } } - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: 0) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings) let statusText: String if let callDuration = callDuration, callDuration > 1 { @@ -265,8 +265,4 @@ class ChatMessageCallBubbleContentNode: ChatMessageBubbleContentNode { return .none } } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - return nil - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageContactBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageContactBubbleContentNode.swift index fb63b3b837..01024dd50e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageContactBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageContactBubbleContentNode.swift @@ -166,20 +166,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings) let statusType: ChatMessageDateAndStatusType? switch position { @@ -208,7 +195,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { isReplyThread = true } - let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: constrainedSize.width, height: CGFloat.greatestFiniteMagnitude), dateReactions, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) + let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: constrainedSize.width, height: CGFloat.greatestFiniteMagnitude), dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) statusSize = size statusApply = apply } @@ -376,11 +363,4 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode { let _ = item.controllerInteraction.openMessage(item.message, .default) } } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - if !self.dateAndStatusNode.isHidden { - return self.dateAndStatusNode.reactionNode(value: value) - } - return nil - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageDateAndStatusNode.swift b/submodules/TelegramUI/Sources/ChatMessageDateAndStatusNode.swift index bba9996b08..c341a56221 100644 --- a/submodules/TelegramUI/Sources/ChatMessageDateAndStatusNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageDateAndStatusNode.swift @@ -9,8 +9,6 @@ import TelegramPresentationData import AccountContext import AppBundle -private let reactionCountFont = Font.semibold(11.0) - private func maybeAddRotationAnimation(_ layer: CALayer, duration: Double) { if let _ = layer.animation(forKey: "clockFrameAnimation") { return @@ -42,112 +40,6 @@ enum ChatMessageDateAndStatusType: Equatable { case FreeOutgoing(ChatMessageDateAndStatusOutgoingType) } -private let reactionFont = Font.regular(12.0) - -private final class StatusReactionNode: ASDisplayNode { - let emptyImageNode: ASImageNode - let selectedImageNode: ASImageNode - - private var theme: PresentationTheme? - private var isSelected: Bool? - - override init() { - self.emptyImageNode = ASImageNode() - self.emptyImageNode.displaysAsynchronously = false - self.selectedImageNode = ASImageNode() - self.selectedImageNode.displaysAsynchronously = false - - super.init() - - self.addSubnode(self.emptyImageNode) - self.addSubnode(self.selectedImageNode) - } - - func update(type: ChatMessageDateAndStatusType, isSelected: Bool, count: Int, theme: PresentationTheme, wallpaper: TelegramWallpaper, animated: Bool) { - if self.theme !== theme { - self.theme = theme - - let emptyImage: UIImage? - let selectedImage: UIImage? - switch type { - case .BubbleIncoming: - emptyImage = PresentationResourcesChat.chatMessageLike(theme, incoming: true, isSelected: false) - selectedImage = PresentationResourcesChat.chatMessageLike(theme, incoming: true, isSelected: true) - case .BubbleOutgoing: - emptyImage = PresentationResourcesChat.chatMessageLike(theme, incoming: false, isSelected: false) - selectedImage = PresentationResourcesChat.chatMessageLike(theme, incoming: false, isSelected: true) - case .ImageIncoming, .ImageOutgoing: - emptyImage = PresentationResourcesChat.chatMessageMediaLike(theme, isSelected: false) - selectedImage = PresentationResourcesChat.chatMessageMediaLike(theme, isSelected: true) - case .FreeIncoming, .FreeOutgoing: - emptyImage = PresentationResourcesChat.chatMessageFreeLike(theme, wallpaper: wallpaper, isSelected: false) - selectedImage = PresentationResourcesChat.chatMessageFreeLike(theme, wallpaper: wallpaper, isSelected: true) - } - - if let emptyImage = emptyImage, let selectedImage = selectedImage { - self.emptyImageNode.image = emptyImage - self.emptyImageNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: emptyImage.size) - - self.selectedImageNode.image = selectedImage - self.selectedImageNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: selectedImage.size) - } - } - - if self.isSelected != isSelected { - let wasSelected = self.isSelected - self.isSelected = isSelected - - self.emptyImageNode.isHidden = isSelected && count <= 1 - self.selectedImageNode.isHidden = !isSelected - - if let wasSelected = wasSelected, wasSelected, !isSelected { - if let image = self.selectedImageNode.image { - let leftImage = generateImage(image.size, rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - UIGraphicsPushContext(context) - image.draw(in: CGRect(origin: CGPoint(), size: size)) - UIGraphicsPopContext() - context.clear(CGRect(origin: CGPoint(x: size.width / 2.0, y: 0.0), size: CGSize(width: size.width / 2.0, height: size.height))) - }) - let rightImage = generateImage(image.size, rotatedContext: { size, context in - context.clear(CGRect(origin: CGPoint(), size: size)) - UIGraphicsPushContext(context) - image.draw(in: CGRect(origin: CGPoint(), size: size)) - UIGraphicsPopContext() - context.clear(CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.width / 2.0, height: size.height))) - }) - if let leftImage = leftImage, let rightImage = rightImage { - let leftView = UIImageView() - leftView.image = leftImage - leftView.frame = self.selectedImageNode.frame - let rightView = UIImageView() - rightView.image = rightImage - rightView.frame = self.selectedImageNode.frame - self.view.addSubview(leftView) - self.view.addSubview(rightView) - - let duration: Double = 0.3 - - leftView.layer.animateRotation(from: 0.0, to: -CGFloat.pi * 0.7, duration: duration, removeOnCompletion: false) - rightView.layer.animateRotation(from: 0.0, to: CGFloat.pi * 0.7, duration: duration, removeOnCompletion: false) - - leftView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: -6.0, y: 8.0), duration: duration, removeOnCompletion: false, additive: true) - rightView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 6.0, y: 8.0), duration: duration, removeOnCompletion: false, additive: true) - - leftView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false, completion: { [weak leftView] _ in - leftView?.removeFromSuperview() - }) - - rightView.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, removeOnCompletion: false, completion: { [weak rightView] _ in - rightView?.removeFromSuperview() - }) - } - } - } - } - } -} - class ChatMessageDateAndStatusNode: ASDisplayNode { private var backgroundNode: ASImageNode? private var blurredBackgroundNode: NavigationBackgroundNode? @@ -157,9 +49,6 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { private var clockMinNode: ASImageNode? private let dateNode: TextNode private var impressionIcon: ASImageNode? - private var reactionNodes: [StatusReactionNode] = [] - private var reactionCountNode: TextNode? - private var reactionButtonNode: HighlightTrackingButtonNode? private var repliesIcon: ASImageNode? private var selfExpiringIcon: ASImageNode? private var replyCountNode: TextNode? @@ -169,8 +58,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { private var layoutSize: CGSize? private var tapGestureRecognizer: UITapGestureRecognizer? - - var openReactions: (() -> Void)? + var openReplies: (() -> Void)? var pressed: (() -> Void)? { didSet { @@ -203,7 +91,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { } } - func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ edited: Bool, _ impressionCount: Int?, _ dateText: String, _ type: ChatMessageDateAndStatusType, _ constrainedSize: CGSize, _ reactions: [MessageReaction], _ replies: Int, _ isPinned: Bool, _ hasAutoremove: Bool) -> (CGSize, (Bool) -> Void) { + func asyncLayout() -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ edited: Bool, _ impressionCount: Int?, _ dateText: String, _ type: ChatMessageDateAndStatusType, _ constrainedSize: CGSize, _ replies: Int, _ isPinned: Bool, _ hasAutoremove: Bool) -> (CGSize, (Bool) -> Void) { let dateLayout = TextNode.asyncLayout(self.dateNode) var checkReadNode = self.checkReadNode @@ -217,13 +105,12 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { let currentType = self.type let currentTheme = self.theme - - let makeReactionCountLayout = TextNode.asyncLayout(self.reactionCountNode) + let makeReplyCountLayout = TextNode.asyncLayout(self.replyCountNode) let previousLayoutSize = self.layoutSize - return { context, presentationData, edited, impressionCount, dateText, type, constrainedSize, reactions, replyCount, isPinned, hasAutoremove in + return { context, presentationData, edited, impressionCount, dateText, type, constrainedSize, replyCount, isPinned, hasAutoremove in let dateColor: UIColor var backgroundImage: UIImage? var blurredBackgroundColor: (UIColor, Bool)? @@ -526,35 +413,10 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { } else if blurredBackgroundColor != nil { backgroundInsets = UIEdgeInsets(top: 2.0, left: 7.0, bottom: 2.0, right: 7.0) } - - let reactionSize: CGFloat = 14.0 - var reactionCountLayoutAndApply: (TextNodeLayout, () -> TextNode)? + var replyCountLayoutAndApply: (TextNodeLayout, () -> TextNode)? - - let reactionSpacing: CGFloat = -4.0 - let reactionTrailingSpacing: CGFloat = 4.0 + var reactionInset: CGFloat = 0.0 - if !reactions.isEmpty { - reactionInset = -1.0 + CGFloat(reactions.count) * reactionSize + CGFloat(reactions.count - 1) * reactionSpacing + reactionTrailingSpacing - - var count = 0 - for reaction in reactions { - count += Int(reaction.count) - } - - let countString: String - if count > 1000000 { - countString = "\(count / 1000000)M" - } else if count > 1000 { - countString = "\(count / 1000)K" - } else { - countString = "\(count)" - } - - let layoutAndApply = makeReactionCountLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: countString, font: dateFont, textColor: dateColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 100.0, height: 100.0))) - reactionInset += max(10.0, layoutAndApply.0.size.width) + 2.0 - reactionCountLayoutAndApply = layoutAndApply - } if replyCount > 0 { let countString: String @@ -737,80 +599,6 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { } var reactionOffset: CGFloat = leftInset - reactionInset + backgroundInsets.left - for i in 0 ..< reactions.count { - let node: StatusReactionNode - if strongSelf.reactionNodes.count > i { - node = strongSelf.reactionNodes[i] - } else { - node = StatusReactionNode() - if strongSelf.reactionNodes.count > i { - let previousNode = strongSelf.reactionNodes[i] - if animated { - previousNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak previousNode] _ in - previousNode?.removeFromSupernode() - }) - } else { - previousNode.removeFromSupernode() - } - strongSelf.reactionNodes[i] = node - } else { - strongSelf.reactionNodes.append(node) - } - } - - node.update(type: type, isSelected: reactions[i].isSelected, count: Int(reactions[i].count), theme: presentationData.theme.theme, wallpaper: presentationData.theme.wallpaper, animated: false) - if node.supernode == nil { - strongSelf.addSubnode(node) - if animated { - node.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - } - } - node.frame = CGRect(origin: CGPoint(x: reactionOffset, y: backgroundInsets.top + offset + 1.0), size: CGSize(width: reactionSize, height: reactionSize)) - reactionOffset += reactionSize + reactionSpacing - } - if !reactions.isEmpty { - reactionOffset += reactionTrailingSpacing - } - for _ in reactions.count ..< strongSelf.reactionNodes.count { - let node = strongSelf.reactionNodes.removeLast() - if animated { - if let previousLayoutSize = previousLayoutSize { - node.frame = node.frame.offsetBy(dx: layoutSize.width - previousLayoutSize.width, dy: 0.0) - } - node.layer.animateScale(from: 1.0, to: 0.1, duration: 0.2, removeOnCompletion: false) - node.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak node] _ in - node?.removeFromSupernode() - }) - } else { - node.removeFromSupernode() - } - } - - if let (layout, apply) = reactionCountLayoutAndApply { - let node = apply() - if strongSelf.reactionCountNode !== node { - strongSelf.reactionCountNode?.removeFromSupernode() - strongSelf.addSubnode(node) - strongSelf.reactionCountNode = node - if animated { - node.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) - } - } - node.frame = CGRect(origin: CGPoint(x: reactionOffset + 1.0, y: backgroundInsets.top + 1.0 + offset), size: layout.size) - reactionOffset += 1.0 + layout.size.width - } else if let reactionCountNode = strongSelf.reactionCountNode { - strongSelf.reactionCountNode = nil - if animated { - if let previousLayoutSize = previousLayoutSize { - reactionCountNode.frame = reactionCountNode.frame.offsetBy(dx: layoutSize.width - previousLayoutSize.width, dy: 0.0) - } - reactionCountNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak reactionCountNode] _ in - reactionCountNode?.removeFromSupernode() - }) - } else { - reactionCountNode.removeFromSupernode() - } - } if let currentRepliesIcon = currentRepliesIcon { currentRepliesIcon.displaysAsynchronously = !presentationData.isPreview @@ -865,50 +653,22 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { replyCountNode.removeFromSupernode() } } - - /*if !strongSelf.reactionNodes.isEmpty { - if strongSelf.reactionButtonNode == nil { - let reactionButtonNode = HighlightTrackingButtonNode() - strongSelf.reactionButtonNode = reactionButtonNode - strongSelf.addSubnode(reactionButtonNode) - reactionButtonNode.addTarget(strongSelf, action: #selector(strongSelf.reactionButtonPressed), forControlEvents: .touchUpInside) - reactionButtonNode.highligthedChanged = { [weak strongSelf] highlighted in - guard let strongSelf = strongSelf else { - return - } - if highlighted { - for itemNode in strongSelf.reactionNodes { - itemNode.alpha = 0.4 - } - } else { - for itemNode in strongSelf.reactionNodes { - itemNode.alpha = 1.0 - itemNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.3) - } - } - } - } - strongSelf.reactionButtonNode?.frame = CGRect(origin: CGPoint(x: leftInset - reactionInset + backgroundInsets.left - 5.0, y: backgroundInsets.top + 1.0 + offset - 5.0), size: CGSize(width: reactionOffset + 5.0 * 2.0, height: 20.0)) - } else if let reactionButtonNode = strongSelf.reactionButtonNode { - strongSelf.reactionButtonNode = nil - reactionButtonNode.removeFromSupernode() - }*/ } }) } } - static func asyncLayout(_ node: ChatMessageDateAndStatusNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ edited: Bool, _ impressionCount: Int?, _ dateText: String, _ type: ChatMessageDateAndStatusType, _ constrainedSize: CGSize, _ reactions: [MessageReaction], _ replies: Int, _ isPinned: Bool, _ hasAutoremove: Bool) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode) { + static func asyncLayout(_ node: ChatMessageDateAndStatusNode?) -> (_ context: AccountContext, _ presentationData: ChatPresentationData, _ edited: Bool, _ impressionCount: Int?, _ dateText: String, _ type: ChatMessageDateAndStatusType, _ constrainedSize: CGSize, _ replies: Int, _ isPinned: Bool, _ hasAutoremove: Bool) -> (CGSize, (Bool) -> ChatMessageDateAndStatusNode) { let currentLayout = node?.asyncLayout() - return { context, presentationData, edited, impressionCount, dateText, type, constrainedSize, reactions, replies, isPinned, hasAutoremove in + return { context, presentationData, edited, impressionCount, dateText, type, constrainedSize, replies, isPinned, hasAutoremove in let resultNode: ChatMessageDateAndStatusNode let resultSizeAndApply: (CGSize, (Bool) -> Void) if let node = node, let currentLayout = currentLayout { resultNode = node - resultSizeAndApply = currentLayout(context, presentationData, edited, impressionCount, dateText, type, constrainedSize, reactions, replies, isPinned, hasAutoremove) + resultSizeAndApply = currentLayout(context, presentationData, edited, impressionCount, dateText, type, constrainedSize, replies, isPinned, hasAutoremove) } else { resultNode = ChatMessageDateAndStatusNode() - resultSizeAndApply = resultNode.asyncLayout()(context, presentationData, edited, impressionCount, dateText, type, constrainedSize, reactions, replies, isPinned, hasAutoremove) + resultSizeAndApply = resultNode.asyncLayout()(context, presentationData, edited, impressionCount, dateText, type, constrainedSize, replies, isPinned, hasAutoremove) } return (resultSizeAndApply.0, { animated in @@ -918,23 +678,7 @@ class ChatMessageDateAndStatusNode: ASDisplayNode { } } - func reactionNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - for node in self.reactionNodes { - return (node.emptyImageNode, node.selectedImageNode) - } - return nil - } - - @objc private func reactionButtonPressed() { - self.openReactions?() - } - override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - if let reactionButtonNode = self.reactionButtonNode { - if reactionButtonNode.frame.contains(point) { - return reactionButtonNode.view - } - } if self.pressed != nil { if self.bounds.contains(point) { return self.view diff --git a/submodules/TelegramUI/Sources/ChatMessageFileBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageFileBubbleContentNode.swift index 45cbb914ab..66e78959cb 100644 --- a/submodules/TelegramUI/Sources/ChatMessageFileBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageFileBubbleContentNode.swift @@ -160,8 +160,4 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode { override func animateRemoved(_ currentTimestamp: Double, duration: Double) { self.interactiveFileNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - return self.interactiveFileNode.reactionTargetNode(value: value) - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageGameBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageGameBubbleContentNode.swift index b17ed19d17..ff96893061 100644 --- a/submodules/TelegramUI/Sources/ChatMessageGameBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageGameBubbleContentNode.swift @@ -139,8 +139,4 @@ final class ChatMessageGameBubbleContentNode: ChatMessageBubbleContentNode { } return self.contentNode.transitionNode(media: media) } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - return self.contentNode.reactionTargetNode(value: value) - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index 917c8abe47..7fec802f35 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift @@ -980,10 +980,6 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD break case .reply: item.controllerInteraction.setupReply(item.message.id) - case .like: - item.controllerInteraction.updateMessageLike(item.message.id, true) - case .unlike: - item.controllerInteraction.updateMessageLike(item.message.id, true) } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift index e3e40ed745..5b425f7342 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveFileNode.swift @@ -320,22 +320,9 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { edited = true } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } + let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings) - let dateText = stringForMessageTimestampStatus(accountPeerId: context.account.peerId, message: message, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, strings: presentationData.strings, reactionCount: dateReactionCount) - - let (size, apply) = statusLayout(context, presentationData, edited, viewCount, dateText, statusType, constrainedSize, dateReactions, dateReplies, isPinned && !associatedData.isInPinnedListMode, message.isSelfExpiring) + let (size, apply) = statusLayout(context, presentationData, edited, viewCount, dateText, statusType, constrainedSize, dateReplies, isPinned && !associatedData.isInPinnedListMode, message.isSelfExpiring) statusSize = size statusApply = apply } @@ -1137,13 +1124,6 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode { self.playerUpdateTimer?.invalidate() self.playerUpdateTimer = nil } - - func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - if !self.dateAndStatusNode.isHidden { - return self.dateAndStatusNode.reactionNode(value: value) - } - return nil - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift index f21aa256bd..cfc01ba572 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift @@ -274,20 +274,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular) let maxDateAndStatusWidth: CGFloat if case .bubble = statusDisplayType { @@ -301,7 +288,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { isReplyThread = true } - let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited && !sentViaBot, viewCount, dateText, statusType, CGSize(width: max(1.0, maxDateAndStatusWidth), height: CGFloat.greatestFiniteMagnitude), dateReactions, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) + let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited && !sentViaBot, viewCount, dateText, statusType, CGSize(width: max(1.0, maxDateAndStatusWidth), height: CGFloat.greatestFiniteMagnitude), dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) var displayVideoFrame = videoFrame displayVideoFrame.size.width *= imageScale diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift index 5b7b0e5f30..323e38ba2e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift @@ -69,7 +69,6 @@ struct ChatMessageDateAndStatus { var edited: Bool var viewCount: Int? var dateReplies: Int - var dateReactions: [MessageReaction] var isPinned: Bool var dateText: String } @@ -468,7 +467,7 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio var statusApply: ((Bool) -> Void)? if let dateAndStatus = dateAndStatus { - let (size, apply) = statusLayout(context, presentationData, dateAndStatus.edited, dateAndStatus.viewCount, dateAndStatus.dateText, dateAndStatus.type, CGSize(width: nativeSize.width - 30.0, height: CGFloat.greatestFiniteMagnitude), dateAndStatus.dateReactions, dateAndStatus.dateReplies, dateAndStatus.isPinned, message.isSelfExpiring) + let (size, apply) = statusLayout(context, presentationData, dateAndStatus.edited, dateAndStatus.viewCount, dateAndStatus.dateText, dateAndStatus.type, CGSize(width: nativeSize.width - 30.0, height: CGFloat.greatestFiniteMagnitude), dateAndStatus.dateReplies, dateAndStatus.isPinned, message.isSelfExpiring) statusSize = size statusApply = apply } diff --git a/submodules/TelegramUI/Sources/ChatMessageInvoiceBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageInvoiceBubbleContentNode.swift index e8f5830a2f..fef2e5cd0d 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInvoiceBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInvoiceBubbleContentNode.swift @@ -135,8 +135,4 @@ final class ChatMessageInvoiceBubbleContentNode: ChatMessageBubbleContentNode { } return self.contentNode.transitionNode(media: media) } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - return self.contentNode.reactionTargetNode(value: value) - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageMapBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageMapBubbleContentNode.swift index 6655607b0f..ef18419e76 100644 --- a/submodules/TelegramUI/Sources/ChatMessageMapBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageMapBubbleContentNode.swift @@ -195,26 +195,13 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - if let selectedMedia = selectedMedia { if selectedMedia.liveBroadcastingTimeout != nil { edited = false } } - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings) let statusType: ChatMessageDateAndStatusType? switch position { @@ -257,7 +244,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { isReplyThread = true } - let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: constrainedSize.width, height: CGFloat.greatestFiniteMagnitude), dateReactions, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) + let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: constrainedSize.width, height: CGFloat.greatestFiniteMagnitude), dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) statusSize = size statusApply = apply } @@ -498,11 +485,4 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode { } } } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - if !self.dateAndStatusNode.isHidden { - return self.dateAndStatusNode.reactionNode(value: value) - } - return nil - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageMediaBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageMediaBubbleContentNode.swift index e5d284ab45..5477264c9c 100644 --- a/submodules/TelegramUI/Sources/ChatMessageMediaBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageMediaBubbleContentNode.swift @@ -167,20 +167,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings) let statusType: ChatMessageDateAndStatusType? switch preparePosition { @@ -213,7 +200,6 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { edited: edited, viewCount: viewCount, dateReplies: dateReplies, - dateReactions: dateReactions, isPinned: item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, dateText: dateText ) @@ -399,11 +385,4 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode { return false } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - /*if !self.dateAndStatusNode.isHidden { - return self.dateAndStatusNode.reactionNode(value: value) - }*/ - return nil - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift index d1c8e94fd8..3333e967ff 100644 --- a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift @@ -112,31 +112,31 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { var isReminder = false var isScheduled = false var title: String? - if let firstMessage = item.messages.first, let peer = messageMainPeer(firstMessage) { - if let channel = peer as? TelegramChannel, case .broadcast = channel.info { - title = EnginePeer(peer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + if let firstMessage = item.messages.first, let peer = messageMainPeer(EngineMessage(firstMessage)) { + if case let .channel(channel) = peer, case .broadcast = channel.info { + title = peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) } else if let author = firstMessage.author { if firstMessage.id.peerId.isReplies, let _ = firstMessage.sourceReference, let effectiveAuthor = firstMessage.forwardInfo?.author { - title = EnginePeer(effectiveAuthor).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + "@" + EnginePeer(peer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + title = EnginePeer(effectiveAuthor).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + "@" + peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) } else if author.id != peer.id { if author.id == item.context.account.peerId { - title = presentationData.strings.DialogList_You + "@" + EnginePeer(peer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + title = presentationData.strings.DialogList_You + "@" + peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) } else { - title = EnginePeer(author).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + "@" + EnginePeer(peer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + title = EnginePeer(author).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + "@" + peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) } } else { - title = EnginePeer(peer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + title = peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) for attribute in firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { if let sourcePeer = firstMessage.peers[attribute.messageId.peerId] { - title = EnginePeer(sourcePeer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + "@" + EnginePeer(peer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + title = EnginePeer(sourcePeer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + "@" + peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) } break } } } } else { - title = EnginePeer(peer).displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) + title = peer.displayTitle(strings: item.strings, displayOrder: item.nameDisplayOrder) } if let _ = title, firstMessage.flags.contains(.WasScheduled) { @@ -148,9 +148,9 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { } var avatarPeer = peer if firstMessage.id.peerId.isReplies, let author = firstMessage.forwardInfo?.author { - avatarPeer = author + avatarPeer = EnginePeer(author) } - self.avatarNode.setPeer(context: item.context, theme: presentationData.theme, peer: EnginePeer(avatarPeer), overrideImage: peer.id == item.context.account.peerId ? .savedMessagesIcon : nil, emptyColor: presentationData.theme.list.mediaPlaceholderColor) + self.avatarNode.setPeer(context: item.context, theme: presentationData.theme, peer: avatarPeer, overrideImage: peer.id == item.context.account.peerId ? .savedMessagesIcon : nil, emptyColor: presentationData.theme.list.mediaPlaceholderColor) } var updatedMedia: Media? @@ -180,7 +180,7 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { if message.containsSecretMedia { imageDimensions = nil } - messageText = descriptionStringForMessage(contentSettings: item.context.currentContentSettings.with { $0 }, message: message, strings: item.strings, nameDisplayOrder: item.nameDisplayOrder, dateTimeFormat: item.dateTimeFormat, accountPeerId: item.context.account.peerId).0 + messageText = descriptionStringForMessage(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: item.strings, nameDisplayOrder: item.nameDisplayOrder, dateTimeFormat: item.dateTimeFormat, accountPeerId: item.context.account.peerId).0 } else if item.messages.count > 1, let peer = item.messages[0].peers[item.messages[0].id.peerId] { var displayAuthor = true if let channel = peer as? TelegramChannel { @@ -205,9 +205,9 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { messageText = presentationData.strings.PUSH_MESSAGE_FWDS_TEXT(Int32(item.messages.count)) } } else if item.messages[0].groupingKey != nil { - var kind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: item.messages[0], strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId).key + var kind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(item.messages[0]), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId).key for i in 1 ..< item.messages.count { - let nextKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: item.messages[i], strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId) + let nextKind = messageContentKind(contentSettings: item.context.currentContentSettings.with { $0 }, message: EngineMessage(item.messages[i]), strings: presentationData.strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: item.context.account.peerId) if kind != nextKind.key { kind = .text break diff --git a/submodules/TelegramUI/Sources/ChatMessagePollBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessagePollBubbleContentNode.swift index 324af61074..232f5e0137 100644 --- a/submodules/TelegramUI/Sources/ChatMessagePollBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessagePollBubbleContentNode.swift @@ -1036,20 +1036,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings) let statusType: ChatMessageDateAndStatusType? switch position { @@ -1078,7 +1065,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { isReplyThread = true } - let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReactions, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) + let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) statusSize = size statusApply = apply } @@ -1744,13 +1731,6 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode { } } - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - if !self.statusNode.isHidden { - return self.statusNode.reactionNode(value: value) - } - return nil - } - func updatePollTooltipMessageState(animated: Bool) { guard let item = self.item else { return diff --git a/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift index 3c5ead8db0..b196e018eb 100644 --- a/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift @@ -64,7 +64,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode { } } - let (textString, isMedia) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: message, strings: strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: context.account.peerId) + let (textString, isMedia) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: presentationData.nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: context.account.peerId) let placeholderColor: UIColor = message.effectivelyIncoming(context.account.peerId) ? presentationData.theme.theme.chat.message.incoming.mediaPlaceholderColor : presentationData.theme.theme.chat.message.outgoing.mediaPlaceholderColor let titleColor: UIColor diff --git a/submodules/TelegramUI/Sources/ChatMessageRestrictedBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageRestrictedBubbleContentNode.swift index 9aafc15d13..dac61792fd 100644 --- a/submodules/TelegramUI/Sources/ChatMessageRestrictedBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageRestrictedBubbleContentNode.swift @@ -67,20 +67,7 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings) let statusType: ChatMessageDateAndStatusType? switch position { @@ -109,7 +96,7 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode { isReplyThread = true } - let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReactions, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && isReplyThread, item.message.isSelfExpiring) + let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && isReplyThread, item.message.isSelfExpiring) statusSize = size statusApply = apply } @@ -252,11 +239,4 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode { self.textNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) self.statusNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - if !self.statusNode.isHidden { - return self.statusNode.reactionNode(value: value) - } - return nil - } } diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index a90140af01..2faae669fb 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -140,13 +140,6 @@ class ChatMessageStickerItemNode: ChatMessageItemView { self.messageAccessibilityArea.focused = { [weak self] in self?.accessibilityElementDidBecomeFocused() } - - self.dateAndStatusNode.openReactions = { [weak self] in - guard let strongSelf = self, let item = strongSelf.item else { - return - } - item.controllerInteraction.openMessageReactions(item.message.id) - } } required init?(coder aDecoder: NSCoder) { @@ -191,7 +184,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { guard let strongSelf = self else { return } - //strongSelf.reactionRecognizer?.cancel() + if let action = strongSelf.gestureRecognized(gesture: .longTap, location: point, recognizer: recognizer) { switch action { case let .action(f): @@ -478,27 +471,14 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: .regular) var isReplyThread = false if case .replyThread = item.chatLocation { isReplyThread = true } - let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), dateReactions, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) + let (dateAndStatusSize, dateAndStatusApply) = makeDateAndStatusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, CGSize(width: params.width, height: CGFloat.greatestFiniteMagnitude), dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) var viaBotApply: (TextNodeLayout, () -> TextNode)? var replyInfoApply: (CGSize, () -> ChatMessageReplyInfoNode)? @@ -1153,10 +1133,6 @@ class ChatMessageStickerItemNode: ChatMessageItemView { break case .reply: item.controllerInteraction.setupReply(item.message.id) - case .like: - item.controllerInteraction.updateMessageLike(item.message.id, true) - case .unlike: - item.controllerInteraction.updateMessageLike(item.message.id, true) } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageSwipeToReplyNode.swift b/submodules/TelegramUI/Sources/ChatMessageSwipeToReplyNode.swift index 6ba2ffb591..bbdee19c02 100644 --- a/submodules/TelegramUI/Sources/ChatMessageSwipeToReplyNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageSwipeToReplyNode.swift @@ -73,10 +73,6 @@ extension ChatMessageSwipeToReplyNode.Action { self = .reply case .reply: self = .reply - case .like: - self = .like - case .unlike: - self = .unlike } } else { self = .reply diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 098a079fd0..1f146f8991 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -65,13 +65,6 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { self.textAccessibilityOverlayNode.openUrl = { [weak self] url in self?.item?.controllerInteraction.openUrl(url, false, false, nil) } - - self.statusNode.openReactions = { [weak self] in - guard let strongSelf = self, let item = strongSelf.item else { - return - } - item.controllerInteraction.openMessageReactions(item.message.id) - } } required init?(coder aDecoder: NSCoder) { @@ -126,26 +119,13 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } - var dateReactions: [MessageReaction] = [] - var dateReactionCount = 0 - if let reactionsAttribute = mergedMessageReactions(attributes: item.message.attributes), !reactionsAttribute.reactions.isEmpty { - for reaction in reactionsAttribute.reactions { - if reaction.isSelected { - dateReactions.insert(reaction, at: 0) - } else { - dateReactions.append(reaction) - } - dateReactionCount += Int(reaction.count) - } - } - let dateFormat: MessageTimestampStatusFormat if let subject = item.associatedData.subject, case .forwardedMessages = subject { dateFormat = .minimal } else { dateFormat = .regular } - let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: dateFormat, reactionCount: dateReactionCount) + let dateText = stringForMessageTimestampStatus(accountPeerId: item.context.account.peerId, message: item.message, dateTimeFormat: item.presentationData.dateTimeFormat, nameDisplayOrder: item.presentationData.nameDisplayOrder, strings: item.presentationData.strings, format: dateFormat) let statusType: ChatMessageDateAndStatusType? var displayStatus = false @@ -184,7 +164,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { isReplyThread = true } - let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReactions, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) + let (size, apply) = statusLayout(item.context, item.presentationData, edited, viewCount, dateText, statusType, textConstrainedSize, dateReplies, item.message.tags.contains(.pinned) && !item.associatedData.isInPinnedListMode && !isReplyThread, item.message.isSelfExpiring) statusSize = size statusApply = apply } @@ -636,13 +616,6 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - if !self.statusNode.isHidden { - return self.statusNode.reactionNode(value: value) - } - return nil - } - override func getStatusNode() -> ASDisplayNode? { return self.statusNode } diff --git a/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift index 4af2ea14f0..aaf9f53ee6 100644 --- a/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift @@ -526,8 +526,4 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode { let contentNodeFrame = self.contentNode.frame self.contentNode.updateTouchesAtPoint(point.flatMap { $0.offsetBy(dx: -contentNodeFrame.minX, dy: -contentNodeFrame.minY) }) } - - override func reactionTargetNode(value: String) -> (ASDisplayNode, ASDisplayNode)? { - return self.contentNode.reactionTargetNode(value: value) - } } diff --git a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift index 701bea9fad..d4158f8c69 100644 --- a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift @@ -451,7 +451,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { } let (titleLayout, titleApply) = makeTitleLayout(CGSize(width: width - textLineInset - contentLeftInset - rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude), titleStrings) - let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: foldLineBreaks(descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: message, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId).0), font: Font.regular(15.0), textColor: message.media.isEmpty || message.media.first is TelegramMediaWebpage ? theme.chat.inputPanel.primaryTextColor : theme.chat.inputPanel.secondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - textLineInset - contentLeftInset - rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 0.0, bottom: 2.0, right: 0.0))) + let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: foldLineBreaks(descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: accountPeerId).0), font: Font.regular(15.0), textColor: message.media.isEmpty || message.media.first is TelegramMediaWebpage ? theme.chat.inputPanel.primaryTextColor : theme.chat.inputPanel.secondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: width - textLineInset - contentLeftInset - rightInset - textRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 0.0, bottom: 2.0, right: 0.0))) Queue.mainQueue().async { if let strongSelf = self { diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 39c5dd6072..06ab336719 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -298,8 +298,6 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { return self?.getNavigationController() }, chatControllerNode: { [weak self] in return self - }, reactionContainerNode: { - return nil }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { [weak self] action, message in if let strongSelf = self { switch action { @@ -507,8 +505,6 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, sendScheduledMessagesNow: { _ in }, editScheduledMessagesTime: { _ in }, performTextSelectionAction: { _, _, _ in - }, updateMessageLike: { _, _ in - }, openMessageReactions: { _ in }, displayImportedMessageTooltip: { _ in }, displaySwipeToReplyHint: { }, dismissReplyMarkupMessage: { _ in diff --git a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift index 18fd8322f8..781e849d67 100644 --- a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift @@ -207,7 +207,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe if let message = messages.first { let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.peerId), subject: .message(id: message.id, highlight: true, timecode: nil), botStart: nil, mode: .standard(previewing: true)) chatController.canReadHistory.set(false) - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(ContextController.Items(items: [])), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(ContextController.Items(items: [])), gesture: gesture) presentInGlobalOverlay(contextController) } else { gesture?.cancel() diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index 4f869e21fb..5421794303 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -115,8 +115,6 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { return nil }, chatControllerNode: { return nil - }, reactionContainerNode: { - return nil }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in }, canSetupReply: { _ in return .none @@ -133,8 +131,6 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { }, sendScheduledMessagesNow: { _ in }, editScheduledMessagesTime: { _ in }, performTextSelectionAction: { _, _, _ in - }, updateMessageLike: { _, _ in - }, openMessageReactions: { _ in }, displayImportedMessageTooltip: { _ in }, displaySwipeToReplyHint: { }, dismissReplyMarkupMessage: { _ in diff --git a/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift index ba008e578c..15a1315d92 100644 --- a/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift @@ -169,7 +169,7 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { if let currentEditMediaReference = self.currentEditMediaReference { effectiveMessage = effectiveMessage.withUpdatedMedia([currentEditMediaReference.media]) } - (text, _) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: effectiveMessage, strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, dateTimeFormat: self.dateTimeFormat, accountPeerId: self.context.account.peerId) + (text, _) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(effectiveMessage), strings: self.strings, nameDisplayOrder: self.nameDisplayOrder, dateTimeFormat: self.dateTimeFormat, accountPeerId: self.context.account.peerId) } var updatedMediaReference: AnyMediaReference? @@ -242,7 +242,7 @@ final class EditAccessoryPanelNode: AccessoryPanelNode { effectiveMessage = effectiveMessage.withUpdatedMedia([currentEditMediaReference.media]) } let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } - switch messageContentKind(contentSettings: self.context.currentContentSettings.with { $0 }, message: effectiveMessage, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: self.context.account.peerId) { + switch messageContentKind(contentSettings: self.context.currentContentSettings.with { $0 }, message: EngineMessage(effectiveMessage), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: presentationData.dateTimeFormat, accountPeerId: self.context.account.peerId) { case .text: isMedia = false default: diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index a3c4762728..a7f50a0d69 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -102,8 +102,6 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu return nil }, chatControllerNode: { return nil - }, reactionContainerNode: { - return nil }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in @@ -125,8 +123,6 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu }, sendScheduledMessagesNow: { _ in }, editScheduledMessagesTime: { _ in }, performTextSelectionAction: { _, _, _ in - }, updateMessageLike: { _, _ in - }, openMessageReactions: { _ in }, displayImportedMessageTooltip: { _ in }, displaySwipeToReplyHint: { }, dismissReplyMarkupMessage: { _ in diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index db08ed5776..2d2c62ba9f 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1866,7 +1866,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }))) } - let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(MessageContextExtractedContentSource(sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], recognizer: nil, gesture: gesture) + let controller = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .extracted(MessageContextExtractedContentSource(sourceNode: node)), items: .single(ContextController.Items(items: items)), recognizer: nil, gesture: gesture) strongSelf.controller?.window?.presentInGlobalOverlay(controller) }) }, activateMessagePinch: { _ in @@ -2006,7 +2006,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD switch previewData { case let .gallery(gallery): gallery.setHintWillBePresentedInPreviewingContext(true) - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceNode: node)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: gallery, sourceNode: node)), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) strongSelf.controller?.presentInGlobalOverlay(contextController) case .instantPage: break @@ -2090,8 +2090,6 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD return self?.controller?.navigationController as? NavigationController }, chatControllerNode: { return nil - }, reactionContainerNode: { - return nil }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { [weak self] content, _ in guard let strongSelf = self else { @@ -2160,8 +2158,6 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, sendScheduledMessagesNow: { _ in }, editScheduledMessagesTime: { _ in }, performTextSelectionAction: { _, _, _ in - }, updateMessageLike: { _, _ in - }, openMessageReactions: { _ in }, displayImportedMessageTooltip: { _ in }, displaySwipeToReplyHint: { }, dismissReplyMarkupMessage: { _ in @@ -2230,7 +2226,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self?.chatInterfaceInteraction.openPeer(peer.id, .default, nil) })) ] - let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single(ContextController.Items(items: items)), gesture: gesture) controller.presentInGlobalOverlay(contextController) } @@ -2829,7 +2825,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD }, synchronousLoad: true) galleryController.setHintWillBePresentedInPreviewingContext(true) - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: .single(ContextController.Items(items: items)), gesture: gesture) strongSelf.controller?.presentInGlobalOverlay(contextController) } @@ -3455,7 +3451,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self.view.endEditing(true) if let sourceNode = self.headerNode.buttonNodes[.mute]?.referenceNode { - let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), gesture: gesture) contextController.dismissed = { [weak self] in if let strongSelf = self { strongSelf.state = strongSelf.state.withHighlightedButton(nil) @@ -3771,7 +3767,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if let sourceNode = self.headerNode.buttonNodes[.more]?.referenceNode { let items = mainItemsImpl?() ?? .single([]) - let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: sourceNode)), items: items |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + let contextController = ContextController(account: self.context.account, presentationData: self.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: sourceNode)), items: items |> map { ContextController.Items(items: $0) }, gesture: gesture) contextController.dismissed = { [weak self] in if let strongSelf = self { strongSelf.state = strongSelf.state.withHighlightedButton(nil) @@ -4440,7 +4436,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } if let sourceNode = strongSelf.headerNode.buttonNodes[.voiceChat]?.referenceNode, let controller = strongSelf.controller { - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), gesture: gesture) contextController.dismissed = { [weak self] in if let strongSelf = self { strongSelf.state = strongSelf.state.withHighlightedButton(nil) @@ -4536,7 +4532,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } if let sourceNode = strongSelf.headerNode.buttonNodes[.voiceChat]?.referenceNode, let controller = strongSelf.controller { - let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), reactionItems: [], gesture: gesture) + let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .reference(PeerInfoContextReferenceContentSource(controller: controller, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), gesture: gesture) contextController.dismissed = { [weak self] in if let strongSelf = self { strongSelf.state = strongSelf.state.withHighlightedButton(nil) @@ -5609,7 +5605,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD let contextController = ContextController(account: accountContext.account, presentationData: self.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatListController, sourceNode: node)), items: accountContextMenuItems(context: accountContext, logout: { [weak self] in self?.logoutAccount(id: id) - }) |> map { ContextController.Items(items: $0) }, reactionItems: [], gesture: gesture) + }) |> map { ContextController.Items(items: $0) }, gesture: gesture) self.controller?.presentInGlobalOverlay(contextController) } else { gesture?.cancel() @@ -6908,7 +6904,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen { }))) } - let controller = ContextController(account: primary.0.account, presentationData: self.presentationData, source: .extracted(SettingsTabBarContextExtractedContentSource(controller: self, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), reactionItems: [], recognizer: nil, gesture: gesture) + let controller = ContextController(account: primary.0.account, presentationData: self.presentationData, source: .extracted(SettingsTabBarContextExtractedContentSource(controller: self, sourceNode: sourceNode)), items: .single(ContextController.Items(items: items)), recognizer: nil, gesture: gesture) self.context.sharedContext.mainWindow?.presentInGlobalOverlay(controller) } } diff --git a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift index 02db078c90..2cff35dd92 100644 --- a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift @@ -106,7 +106,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { authorName = EnginePeer(author).displayTitle(strings: strings, displayOrder: nameDisplayOrder) } if let message = message { - (text, _) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: message, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId) + (text, _) = descriptionStringForMessage(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId) } var updatedMediaReference: AnyMediaReference? @@ -172,7 +172,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { let isMedia: Bool if let message = message { - switch messageContentKind(contentSettings: context.currentContentSettings.with { $0 }, message: message, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId) { + switch messageContentKind(contentSettings: context.currentContentSettings.with { $0 }, message: EngineMessage(message), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, accountPeerId: context.account.peerId) { case .text: isMedia = false default: diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index d66ce27f67..9b79c3e0ea 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1254,8 +1254,6 @@ public final class SharedAccountContextImpl: SharedAccountContext { return nil }, chatControllerNode: { return nil - }, reactionContainerNode: { - return nil }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in }, canSetupReply: { _ in return .none @@ -1272,8 +1270,6 @@ public final class SharedAccountContextImpl: SharedAccountContext { }, sendScheduledMessagesNow: { _ in }, editScheduledMessagesTime: { _ in }, performTextSelectionAction: { _, _, _ in - }, updateMessageLike: { _, _ in - }, openMessageReactions: { _ in }, displayImportedMessageTooltip: { _ in }, displaySwipeToReplyHint: { }, dismissReplyMarkupMessage: { _ in diff --git a/submodules/TelegramUI/Sources/StringForMessageTimestampStatus.swift b/submodules/TelegramUI/Sources/StringForMessageTimestampStatus.swift index c3ba9fb771..79b793522b 100644 --- a/submodules/TelegramUI/Sources/StringForMessageTimestampStatus.swift +++ b/submodules/TelegramUI/Sources/StringForMessageTimestampStatus.swift @@ -28,7 +28,7 @@ private func dateStringForDay(strings: PresentationStrings, dateTimeFormat: Pres } } -func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Message, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, strings: PresentationStrings, format: MessageTimestampStatusFormat = .regular, reactionCount: Int) -> String { +func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Message, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, strings: PresentationStrings, format: MessageTimestampStatusFormat = .regular) -> String { if message.adAttribute != nil { return strings.Message_SponsoredLabel } diff --git a/submodules/TelegramUI/Sources/WebpagePreviewAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/WebpagePreviewAccessoryPanelNode.swift index e8c472d253..3ea6d8a12c 100644 --- a/submodules/TelegramUI/Sources/WebpagePreviewAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/WebpagePreviewAccessoryPanelNode.swift @@ -128,7 +128,7 @@ final class WebpagePreviewAccessoryPanelNode: AccessoryPanelNode { if let contentText = content.text { text = contentText } else { - if let file = content.file, let mediaKind = mediaContentKind(file) { + if let file = content.file, let mediaKind = mediaContentKind(EngineMedia(file)) { if content.type == "telegram_background" { text = strings.Message_Wallpaper } else if content.type == "telegram_theme" {