From 03f696fd8fe7925da656fb015da20a5601689731 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 29 Oct 2021 19:27:10 +0400 Subject: [PATCH] Calendar --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/ChatController.swift | 7 +- .../Sources/CalendarMessageScreen.swift | 143 ++++++++++--- .../Sources/ChatListController.swift | 4 +- .../Sources/HashtagSearchController.swift | 2 +- .../Sources/SparseItemGrid.swift | 2 +- .../Sources/ChannelStatsController.swift | 2 +- .../Sources/MessageStatsController.swift | 2 +- .../Sources/ApplicationContext.swift | 4 +- .../TelegramUI/Sources/ChatController.swift | 197 +++++++++++++----- .../Sources/ChatControllerInteraction.swift | 6 +- .../Sources/ChatHistoryListNode.swift | 22 +- .../ChatMessageAnimatedStickerItemNode.swift | 2 +- .../Sources/ChatMessageBubbleItemNode.swift | 2 +- .../Sources/ChatMessageDateHeader.swift | 10 +- .../ChatMessageInstantVideoItemNode.swift | 2 +- .../TelegramUI/Sources/ChatMessageItem.swift | 4 +- .../Sources/ChatMessageStickerItemNode.swift | 2 +- .../ChatMessageWebpageBubbleContentNode.swift | 2 +- .../ChatRecentActionsControllerNode.swift | 6 +- .../ChatSearchResultsContollerNode.swift | 2 +- .../Sources/DrawingStickersScreen.swift | 2 +- .../Sources/NavigateToChatController.swift | 22 +- .../TelegramUI/Sources/OpenResolvedUrl.swift | 2 +- .../OverlayAudioPlayerControllerNode.swift | 6 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 131 ++++++------ .../Sources/SharedAccountContext.swift | 2 +- .../TelegramUI/Sources/TextLinkHandling.swift | 2 +- .../UrlHandling/Sources/UrlHandling.swift | 2 +- 29 files changed, 402 insertions(+), 192 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 01822f31a3..8f75f8106a 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7032,3 +7032,5 @@ Sorry for the inconvenience."; "Themes.BuildOwn" = "Build Your Own Theme"; "Themes.EditCurrentTheme" = "Edit Current Theme"; "Themes.CreateNewTheme" = "Create a New Theme"; + +"Chat.JumpToDate" = "Jump to Date"; diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 335fe15d45..18ecd6a987 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -364,6 +364,11 @@ public struct ChatTextInputStateText: Codable, Equatable { } public enum ChatControllerSubject: Equatable { + public enum MessageSubject: Equatable { + case id(MessageId) + case timestamp(Int32) + } + public struct ForwardOptions: Equatable { public let hideNames: Bool public let hideCaptions: Bool @@ -374,7 +379,7 @@ public enum ChatControllerSubject: Equatable { } } - case message(id: EngineMessage.Id, highlight: Bool, timecode: Double?) + case message(id: MessageSubject, highlight: Bool, timecode: Double?) case scheduledMessages case pinnedMessages(id: EngineMessage.Id?) case forwardedMessages(ids: [EngineMessage.Id], options: Signal) diff --git a/submodules/CalendarMessageScreen/Sources/CalendarMessageScreen.swift b/submodules/CalendarMessageScreen/Sources/CalendarMessageScreen.swift index febeed8922..361e6f2f46 100644 --- a/submodules/CalendarMessageScreen/Sources/CalendarMessageScreen.swift +++ b/submodules/CalendarMessageScreen/Sources/CalendarMessageScreen.swift @@ -364,6 +364,7 @@ private final class DayComponent: Component { let isEnabled: Bool let theme: PresentationTheme let context: AccountContext + let timestamp: Int32 let media: DayMedia? let selection: DaySelection let isSelecting: Bool @@ -375,6 +376,7 @@ private final class DayComponent: Component { isEnabled: Bool, theme: PresentationTheme, context: AccountContext, + timestamp: Int32, media: DayMedia?, selection: DaySelection, isSelecting: Bool, @@ -385,6 +387,7 @@ private final class DayComponent: Component { self.isEnabled = isEnabled self.theme = theme self.context = context + self.timestamp = timestamp self.media = media self.selection = selection self.isSelecting = isSelecting @@ -410,6 +413,9 @@ private final class DayComponent: Component { if lhs.media != rhs.media { return false } + if lhs.timestamp != rhs.timestamp { + return false + } if lhs.selection != rhs.selection { return false } @@ -430,6 +436,7 @@ private final class DayComponent: Component { private var action: (() -> Void)? private var currentMedia: DayMedia? + private(set) var timestamp: Int32? private(set) var index: MessageIndex? private var isHighlightingEnabled: Bool = false @@ -473,6 +480,7 @@ private final class DayComponent: Component { let isFirstTime = self.action == nil self.action = component.action + self.timestamp = component.timestamp self.index = component.media?.message.index self.isHighlightingEnabled = component.isEnabled && component.media != nil && !component.isSelecting @@ -745,6 +753,7 @@ private final class MonthComponent: CombinedComponent { isEnabled: isEnabled, theme: context.component.theme, context: context.component.context, + timestamp: dayTimestamp, media: context.component.model.mediaByDay[index], selection: daySelection, isSelecting: context.component.selectedDays != nil, @@ -959,8 +968,10 @@ public final class CalendarMessageScreen: ViewController { private let context: AccountContext private let peerId: PeerId private let initialTimestamp: Int32 - private let navigateToOffset: (Int) -> Void - private let previewDay: (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void + private let enableMessageRangeDeletion: Bool + private let canNavigateToEmptyDays: Bool + private let navigateToOffset: (Int, Int32) -> Void + private let previewDay: (Int32, MessageIndex?, ASDisplayNode, CGRect, ContextGesture) -> Void private var presentationData: PresentationData private var scrollView: Scroller @@ -988,11 +999,23 @@ public final class CalendarMessageScreen: ViewController { private var ignoreContentOffset: Bool = false - init(controller: CalendarMessageScreen, context: AccountContext, peerId: PeerId, calendarSource: SparseMessageCalendar, initialTimestamp: Int32, navigateToOffset: @escaping (Int) -> Void, previewDay: @escaping (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void) { + init( + controller: CalendarMessageScreen, + context: AccountContext, + peerId: PeerId, + calendarSource: SparseMessageCalendar, + initialTimestamp: Int32, + enableMessageRangeDeletion: Bool, + canNavigateToEmptyDays: Bool, + navigateToOffset: @escaping (Int, Int32) -> Void, + previewDay: @escaping (Int32, MessageIndex?, ASDisplayNode, CGRect, ContextGesture) -> Void + ) { self.controller = controller self.context = context self.peerId = peerId self.initialTimestamp = initialTimestamp + self.enableMessageRangeDeletion = enableMessageRangeDeletion + self.canNavigateToEmptyDays = canNavigateToEmptyDays self.calendarSource = calendarSource self.navigateToOffset = navigateToOffset self.previewDay = previewDay @@ -1086,8 +1109,11 @@ public final class CalendarMessageScreen: ViewController { currentGestureDayView.isUserInteractionEnabled = false currentGestureDayView.isUserInteractionEnabled = true - if let index = currentGestureDayView.index { - strongSelf.previewDay(index, strongSelf, currentGestureDayView.convert(currentGestureDayView.bounds, to: strongSelf.view), gesture) + if currentGestureDayView.index == nil && !strongSelf.canNavigateToEmptyDays { + return + } + if let timestamp = currentGestureDayView.timestamp { + strongSelf.previewDay(timestamp, currentGestureDayView.index, strongSelf, currentGestureDayView.convert(currentGestureDayView.bounds, to: strongSelf.view), gesture) } } @@ -1174,6 +1200,21 @@ public final class CalendarMessageScreen: ViewController { } } + func selectDay(timestamp: Int32) { + self.selectionState = SelectionState(dayRange: timestamp ... timestamp) + + self.contextGestureContainerNode.isGestureEnabled = self.selectionState == nil + + if let (layout, navigationHeight) = self.validLayout { + self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .animated(duration: 0.5, curve: .spring)) + } + } + + func openClearHistory(timestamp: Int32) { + self.selectionState = SelectionState(dayRange: timestamp ... timestamp) + self.selectionToolbarActionSelected() + } + func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) { let isFirstLayout = self.validLayout == nil self.validLayout = (layout, navigationHeight) @@ -1292,8 +1333,8 @@ public final class CalendarMessageScreen: ViewController { let dayTimestamp = firstDayTimestamp + 24 * 60 * 60 * Int32(day) let nextDayTimestamp = dayTimestamp + 24 * 60 * 60 - let minDayTimestamp = dayTimestamp - 24 * 60 * 60 - let maxDayTimestamp = nextDayTimestamp - 24 * 60 * 60 + let minDayTimestamp = dayTimestamp + let maxDayTimestamp = nextDayTimestamp if dayRange.contains(dayTimestamp) { if let currentMinTimestamp = minTimestamp { @@ -1401,6 +1442,13 @@ public final class CalendarMessageScreen: ViewController { return } let _ = strongSelf.calendarSource.removeMessagesInRange(minTimestamp: minTimestampValue, maxTimestamp: maxTimestampValue, type: type, completion: { + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + + strongSelf.controller?.dismiss(completion: nil) + } }) } @@ -1423,18 +1471,6 @@ public final class CalendarMessageScreen: ViewController { actionSheet?.dismissAnimated() beginClear(.forEveryone) - - /*guard let strongSelf = self else { - return - } - - strongSelf.controller?.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationTitle, text: confirmationText, actions: [ - TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: { - }), - TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationAction, action: { - beginClear(.forEveryone) - }) - ], parseMarkdown: true), in: .window(.root))*/ })) } if let canClearForMyself = info.canClearForMyself { @@ -1588,7 +1624,7 @@ public final class CalendarMessageScreen: ViewController { for day in 0 ..< month.numberOfDays { let dayTimestamp = firstDayTimestamp + 24 * 60 * 60 * Int32(day) if dayTimestamp == timestamp { - if month.mediaByDay[day] != nil { + if month.mediaByDay[day] != nil || strongSelf.canNavigateToEmptyDays { var offset = 0 for key in calendarState.messagesByDay.keys.sorted(by: { $0 > $1 }) { if key == dayTimestamp { @@ -1597,7 +1633,7 @@ public final class CalendarMessageScreen: ViewController { offset += item.count } } - strongSelf.navigateToOffset(offset) + strongSelf.navigateToOffset(offset, dayTimestamp) } break outer @@ -1709,16 +1745,29 @@ public final class CalendarMessageScreen: ViewController { private let peerId: PeerId private let calendarSource: SparseMessageCalendar private let initialTimestamp: Int32 - private let navigateToDay: (CalendarMessageScreen, Int) -> Void - private let previewDay: (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void + private let enableMessageRangeDeletion: Bool + private let canNavigateToEmptyDays: Bool + private let navigateToDay: (CalendarMessageScreen, Int, Int32) -> Void + private let previewDay: (Int32, MessageIndex?, ASDisplayNode, CGRect, ContextGesture) -> Void private var presentationData: PresentationData - public init(context: AccountContext, peerId: PeerId, calendarSource: SparseMessageCalendar, initialTimestamp: Int32, navigateToDay: @escaping (CalendarMessageScreen, Int) -> Void, previewDay: @escaping (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void) { + public init( + context: AccountContext, + peerId: PeerId, + calendarSource: SparseMessageCalendar, + initialTimestamp: Int32, + enableMessageRangeDeletion: Bool, + canNavigateToEmptyDays: Bool, + navigateToDay: @escaping (CalendarMessageScreen, Int, Int32) -> Void, + previewDay: @escaping (Int32, MessageIndex?, ASDisplayNode, CGRect, ContextGesture) -> Void + ) { self.context = context self.peerId = peerId self.calendarSource = calendarSource self.initialTimestamp = initialTimestamp + self.enableMessageRangeDeletion = enableMessageRangeDeletion + self.canNavigateToEmptyDays = canNavigateToEmptyDays self.navigateToDay = navigateToDay self.previewDay = previewDay @@ -1731,9 +1780,11 @@ public final class CalendarMessageScreen: ViewController { self.navigationItem.setLeftBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(dismissPressed)), animated: false) self.navigationItem.setTitle(self.presentationData.strings.MessageCalendar_Title, animated: false) - /*if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.SecretChat { - self.navigationItem.setRightBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Select, style: .plain, target: self, action: #selector(self.toggleSelectPressed)), animated: false) - }*/ + if self.enableMessageRangeDeletion { + if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.SecretChat { + self.navigationItem.setRightBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Select, style: .plain, target: self, action: #selector(self.toggleSelectPressed)), animated: false) + } + } } required public init(coder aDecoder: NSCoder) { @@ -1745,6 +1796,10 @@ public final class CalendarMessageScreen: ViewController { } @objc fileprivate func toggleSelectPressed() { + if !self.enableMessageRangeDeletion { + return + } + self.node.toggleSelectionMode() if self.node.selectionState != nil { @@ -1754,13 +1809,35 @@ public final class CalendarMessageScreen: ViewController { } } + public func selectDay(timestamp: Int32) { + self.node.selectDay(timestamp: timestamp) + + if self.node.selectionState != nil { + self.navigationItem.setRightBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Done, style: .done, target: self, action: #selector(self.toggleSelectPressed)), animated: true) + } + } + + public func openClearHistory(timestamp: Int32) { + self.node.openClearHistory(timestamp: timestamp) + } + override public func loadDisplayNode() { - self.displayNode = Node(controller: self, context: self.context, peerId: self.peerId, calendarSource: self.calendarSource, initialTimestamp: self.initialTimestamp, navigateToOffset: { [weak self] index in - guard let strongSelf = self else { - return - } - strongSelf.navigateToDay(strongSelf, index) - }, previewDay: self.previewDay) + self.displayNode = Node( + controller: self, + context: self.context, + peerId: self.peerId, + calendarSource: self.calendarSource, + initialTimestamp: self.initialTimestamp, + enableMessageRangeDeletion: self.enableMessageRangeDeletion, + canNavigateToEmptyDays: self.canNavigateToEmptyDays, + navigateToOffset: { [weak self] index, timestamp in + guard let strongSelf = self else { + return + } + strongSelf.navigateToDay(strongSelf, index, timestamp) + }, + previewDay: self.previewDay + ) self.displayNodeDidLoad() } diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index d9675b81bd..47c351d864 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -691,7 +691,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass { scrollToEndIfExists = true } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), subject: .message(id: messageId, highlight: true, timecode: nil), purposefulAction: { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), purposefulAction: { if deactivateOnAction { self?.deactivateSearch(animated: false) } @@ -861,7 +861,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } else { var subject: ChatControllerSubject? if case let .search(messageId) = source, let id = messageId { - subject = .message(id: id, highlight: false, timecode: nil) + subject = .message(id: .id(id), highlight: false, timecode: nil) } let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.id), subject: subject, botStart: nil, mode: .standard(previewing: true)) chatController.canReadHistory.set(false) diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index 820973d3f0..31b9dc9796 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -56,7 +56,7 @@ public final class HashtagSearchController: TelegramBaseController { if let strongSelf = self { strongSelf.openMessageFromSearchDisposable.set((storedMessageFromSearchPeer(account: strongSelf.context.account, peer: peer._asPeer()) |> deliverOnMainQueue).start(next: { actualPeerId in if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), subject: message.id.peerId == actualPeerId ? .message(id: message.id, highlight: true, timecode: nil) : nil, keepStack: .always)) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), subject: message.id.peerId == actualPeerId ? .message(id: .id(message.id), highlight: true, timecode: nil) : nil, keepStack: .always)) } })) strongSelf.controllerNode.listNode.clearHighlightAnimated(true) diff --git a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift index 8c5f6fdd1f..21c9457610 100644 --- a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift +++ b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift @@ -1119,7 +1119,7 @@ public final class SparseItemGrid: ASDisplayNode { let previousProgress = self.currentProgress self.currentProgress = progress - let fixedAnchorPoint = CGPoint(x: fromAnchorFrame.minX + 1.0, y: fromAnchorFrame.minY + 1.0) + let fixedAnchorPoint = CGPoint(x: toAnchorFrame.midX, y: toAnchorFrame.midY) if let fromItem = self.fromViewport.anchorItem(at: fixedAnchorPoint), let fromFrame = self.fromViewport.frameForItem(at: fromItem.index) { fromAnchorFrame.origin.y = fromFrame.midY diff --git a/submodules/StatisticsUI/Sources/ChannelStatsController.swift b/submodules/StatisticsUI/Sources/ChannelStatsController.swift index 1cf81bf1b5..0571023873 100644 --- a/submodules/StatisticsUI/Sources/ChannelStatsController.swift +++ b/submodules/StatisticsUI/Sources/ChannelStatsController.swift @@ -518,7 +518,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD items.append(.action(ContextMenuActionItem(text: presentationData.strings.SharedMedia_ViewInChat, icon: { theme in generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) }, action: { [weak controller] c, _ in c.dismiss(completion: { if let navigationController = controller?.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: .message(id: messageId, highlight: true, timecode: nil))) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) } }) }))) diff --git a/submodules/StatisticsUI/Sources/MessageStatsController.swift b/submodules/StatisticsUI/Sources/MessageStatsController.swift index 83567a43b7..5cca507484 100644 --- a/submodules/StatisticsUI/Sources/MessageStatsController.swift +++ b/submodules/StatisticsUI/Sources/MessageStatsController.swift @@ -263,7 +263,7 @@ public func messageStatsController(context: AccountContext, messageId: MessageId } navigateToMessageImpl = { [weak controller] messageId in if let navigationController = controller?.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(messageId.peerId), subject: .message(id: messageId, highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: {}, peekData: nil)) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(messageId.peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: {}, peekData: nil)) } } return controller diff --git a/submodules/TelegramUI/Sources/ApplicationContext.swift b/submodules/TelegramUI/Sources/ApplicationContext.swift index efa13b46f4..ed722fc2c8 100644 --- a/submodules/TelegramUI/Sources/ApplicationContext.swift +++ b/submodules/TelegramUI/Sources/ApplicationContext.swift @@ -758,7 +758,7 @@ final class AuthorizedApplicationContext { } let navigateToMessage = { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: strongSelf.rootController, context: strongSelf.context, chatLocation: .peer(messageId.peerId), subject: .message(id: messageId, highlight: true, timecode: nil))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: strongSelf.rootController, context: strongSelf.context, chatLocation: .peer(messageId.peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) } if chatIsVisible { @@ -837,7 +837,7 @@ final class AuthorizedApplicationContext { if visiblePeerId != peerId || messageId != nil { if self.rootController.rootTabController != nil { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: .peer(peerId), subject: messageId.flatMap { .message(id: $0, highlight: true, timecode: nil) }, activateInput: activateInput)) + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: .peer(peerId), subject: messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) }, activateInput: activateInput)) } else { self.scheduledOpenChatWithPeerId = (peerId, messageId, activateInput) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 3022ac06e2..bba62cc65a 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -63,6 +63,7 @@ import Speak import UniversalMediaPlayer import WallpaperBackgroundNode import ChatListUI +import CalendarMessageScreen #if DEBUG import os.signpost @@ -2100,16 +2101,20 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } return .none - }, navigateToFirstDateMessage: { [weak self] timestamp in + }, navigateToFirstDateMessage: { [weak self] timestamp, alreadyThere in guard let strongSelf = self else { return } switch strongSelf.chatLocation { - case let .peer(peerId): - strongSelf.navigateToMessage(from: nil, to: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 0), timestamp: timestamp - Int32(NSTimeZone.local.secondsFromGMT()))), scrollPosition: .bottom(0.0), rememberInStack: false, animated: true, completion: nil) - case let .replyThread(replyThreadMessage): - let peerId = replyThreadMessage.messageId.peerId + case let .peer(peerId): + if alreadyThere { + strongSelf.openCalendarSearch(timestamp: timestamp) + } else { strongSelf.navigateToMessage(from: nil, to: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 0), timestamp: timestamp - Int32(NSTimeZone.local.secondsFromGMT()))), scrollPosition: .bottom(0.0), rememberInStack: false, animated: true, completion: nil) + } + case let .replyThread(replyThreadMessage): + let peerId = replyThreadMessage.messageId.peerId + strongSelf.navigateToMessage(from: nil, to: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 0), timestamp: timestamp - Int32(NSTimeZone.local.secondsFromGMT()))), scrollPosition: .bottom(0.0), rememberInStack: false, animated: true, completion: nil) } }, requestRedeliveryOfFailedMessages: { [weak self] id in guard let strongSelf = self else { @@ -5006,7 +5011,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.chatDisplayNode.historyNode.scrolledToIndex = { [weak self] toIndex, initial in if let strongSelf = self, case let .message(index) = toIndex { - if case let .message(messageId, _, _) = strongSelf.subject, initial, messageId != index.id { + if case let .message(messageSubject, _, _) = strongSelf.subject, initial, case let .id(messageId) = messageSubject, messageId != index.id { strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .info(text: strongSelf.presentationData.strings.Conversation_MessageDoesntExist), elevatedLayout: false, action: { _ in return true }), in: .current) } else if let controllerInteraction = strongSelf.controllerInteraction { if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(index.id) { @@ -6076,37 +6081,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } }, openCalendarSearch: { [weak self] in - if let strongSelf = self { - strongSelf.chatDisplayNode.dismissInput() - - let controller = ChatDateSelectionSheet(presentationData: strongSelf.presentationData, completion: { timestamp in - guard let strongSelf = self else { - return - } - strongSelf.loadingMessage.set(.single(.generic)) - - let peerId: PeerId - let threadId: Int64? - switch strongSelf.chatLocation { - case let .peer(peerIdValue): - peerId = peerIdValue - threadId = nil - case let .replyThread(replyThreadMessage): - peerId = replyThreadMessage.messageId.peerId - threadId = makeMessageThreadId(replyThreadMessage.messageId) - } - - strongSelf.messageIndexDisposable.set((strongSelf.context.engine.messages.searchMessageIdByTimestamp(peerId: peerId, threadId: threadId, timestamp: timestamp) |> deliverOnMainQueue).start(next: { messageId in - if let strongSelf = self { - strongSelf.loadingMessage.set(.single(nil)) - if let messageId = messageId { - strongSelf.navigateToMessage(from: nil, to: .id(messageId, nil), forceInCurrentChat: true) - } - } - })) - }) - strongSelf.present(controller, in: .window(.root)) - } + self?.openCalendarSearch(timestamp: Int32(Date().timeIntervalSince1970)) }, toggleMembersSearch: { [weak self] value in if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in @@ -7288,7 +7263,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if let navigationController = strongSelf.effectiveNavigationController { - let subject: ChatControllerSubject? = sourceMessageId.flatMap { ChatControllerSubject.message(id: $0, highlight: true, timecode: nil) } + let subject: ChatControllerSubject? = sourceMessageId.flatMap { ChatControllerSubject.message(id: .id($0), highlight: true, timecode: nil) } strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(replyThreadResult), subject: subject, keepStack: .always)) } }, activatePinnedListPreview: { [weak self] node, gesture in @@ -11308,6 +11283,127 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) }) } + + private func openCalendarSearch(timestamp: Int32) { + guard case let .peer(peerId) = self.chatLocation else { + return + } + self.chatDisplayNode.dismissInput() + + let initialTimestamp = timestamp + var dismissCalendarScreen: (() -> Void)? + var selectDay: ((Int32) -> Void)? + var openClearHistory: ((Int32) -> Void)? + + let calendarScreen = CalendarMessageScreen( + context: self.context, + peerId: peerId, + calendarSource: self.context.engine.messages.sparseMessageCalendar(peerId: peerId, tag: .photoOrVideo), + initialTimestamp: initialTimestamp, + enableMessageRangeDeletion: true, + canNavigateToEmptyDays: true, + navigateToDay: { [weak self] c, index, timestamp in + guard let strongSelf = self else { + c.dismiss() + return + } + + c.dismiss() + + strongSelf.loadingMessage.set(.single(.generic)) + + let peerId: PeerId + let threadId: Int64? + switch strongSelf.chatLocation { + case let .peer(peerIdValue): + peerId = peerIdValue + threadId = nil + case let .replyThread(replyThreadMessage): + peerId = replyThreadMessage.messageId.peerId + threadId = makeMessageThreadId(replyThreadMessage.messageId) + } + + strongSelf.messageIndexDisposable.set((strongSelf.context.engine.messages.searchMessageIdByTimestamp(peerId: peerId, threadId: threadId, timestamp: timestamp) |> deliverOnMainQueue).start(next: { messageId in + if let strongSelf = self { + strongSelf.loadingMessage.set(.single(nil)) + if let messageId = messageId { + strongSelf.navigateToMessage(from: nil, to: .id(messageId, nil), forceInCurrentChat: true) + } + } + })) + }, + previewDay: { [weak self] timestamp, _, sourceNode, sourceRect, gesture in + guard let strongSelf = self else { + return + } + + var items: [ContextMenuItem] = [] + + items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Chat_JumpToDate, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) + }, action: { _, f in + f(.dismissWithoutContent) + dismissCalendarScreen?() + + strongSelf.loadingMessage.set(.single(.generic)) + + let peerId: PeerId + let threadId: Int64? + switch strongSelf.chatLocation { + case let .peer(peerIdValue): + peerId = peerIdValue + threadId = nil + case let .replyThread(replyThreadMessage): + peerId = replyThreadMessage.messageId.peerId + threadId = makeMessageThreadId(replyThreadMessage.messageId) + } + + strongSelf.messageIndexDisposable.set((strongSelf.context.engine.messages.searchMessageIdByTimestamp(peerId: peerId, threadId: threadId, timestamp: timestamp) |> deliverOnMainQueue).start(next: { messageId in + if let strongSelf = self { + strongSelf.loadingMessage.set(.single(nil)) + if let messageId = messageId { + strongSelf.navigateToMessage(from: nil, to: .id(messageId, nil), forceInCurrentChat: true) + } + } + })) + }))) + + if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.SecretChat { + items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.DialogList_ClearHistoryConfirmation, textColor: .destructive, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Delete"), color: theme.contextMenu.destructiveColor) + }, action: { _, f in + f(.dismissWithoutContent) + openClearHistory?(timestamp) + }))) + + items.append(.separator) + + items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Common_Select, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Select"), color: theme.contextMenu.primaryColor) + }, action: { _, f in + f(.dismissWithoutContent) + selectDay?(timestamp) + }))) + } + + let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peerId), subject: .message(id: .timestamp(timestamp), highlight: false, 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: sourceNode, sourceRect: sourceRect, passthroughTouches: true)), items: .single(ContextController.Items(items: items)), gesture: gesture) + strongSelf.presentInGlobalOverlay(contextController) + } + ) + + self.push(calendarScreen) + dismissCalendarScreen = { [weak calendarScreen] in + calendarScreen?.dismiss(completion: nil) + } + selectDay = { [weak calendarScreen] timestamp in + calendarScreen?.selectDay(timestamp: timestamp) + } + openClearHistory = { [weak calendarScreen] timestamp in + calendarScreen?.openClearHistory(timestamp: timestamp) + } + } private func openMessageReplies(messageId: MessageId, displayProgressInMessage: MessageId?, isChannelPost: Bool, atMessage atMessageId: MessageId?, displayModalProgress: Bool) { guard let navigationController = self.navigationController as? NavigationController else { @@ -11382,9 +11478,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let subject: ChatControllerSubject? if let atMessageId = atMessageId { - subject = .message(id: atMessageId, highlight: true, timecode: nil) + subject = .message(id: .id(atMessageId), highlight: true, timecode: nil) } else if let index = result.scrollToLowerBoundMessage { - subject = .message(id: index.id, highlight: false, timecode: nil) + subject = .message(id: .id(index.id), highlight: false, timecode: nil) } else { subject = nil } @@ -11447,11 +11543,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if isPinnedMessages, let messageId = messageLocation.messageId { if let navigationController = self.effectiveNavigationController { self.dismiss() - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), subject: .message(id: messageId, highlight: true, timecode: nil), keepStack: .always)) + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always)) } } else if case let .peer(peerId) = self.chatLocation, let messageId = messageLocation.messageId, (messageId.peerId != peerId && !forceInCurrentChat) || (isScheduledMessages && messageId.id != 0 && !Namespaces.Message.allScheduled.contains(messageId.namespace)) { if let navigationController = self.effectiveNavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), subject: .message(id: messageId, highlight: true, timecode: nil), keepStack: .always)) + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), subject: .message(id: .id(messageId), highlight: true, timecode: nil), keepStack: .always)) } } else if forceInCurrentChat { if let _ = fromId, let fromIndex = fromIndex, rememberInStack { @@ -11613,7 +11709,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G completion?() } else { if let navigationController = strongSelf.effectiveNavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message(id: $0, highlight: true, timecode: nil) })) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) })) } completion?() } @@ -11625,7 +11721,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G })) } else { if let navigationController = self.effectiveNavigationController { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message(id: $0, highlight: true, timecode: nil) })) + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message(id: .id($0), highlight: true, timecode: nil) })) } completion?() } @@ -12399,8 +12495,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G switch navigation { case let .chat(_, subject, peekData): if case .peer(peerId) = strongSelf.chatLocation { - if let subject = subject, case let .message(messageId, _, timecode) = subject { - strongSelf.navigateToMessage(from: sourceMessageId, to: .id(messageId, timecode)) + if let subject = subject, case let .message(messageSubject, _, timecode) = subject { + if case let .id(messageId) = messageSubject { + strongSelf.navigateToMessage(from: sourceMessageId, to: .id(messageId, timecode)) + } } } else if let navigationController = strongSelf.effectiveNavigationController { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: subject, keepStack: .always, peekData: peekData)) @@ -13604,22 +13702,25 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private final class ContextControllerContentSourceImpl: ContextControllerContentSource { let controller: ViewController weak var sourceNode: ASDisplayNode? + let sourceRect: CGRect? let navigationController: NavigationController? = nil let passthroughTouches: Bool - init(controller: ViewController, sourceNode: ASDisplayNode?, passthroughTouches: Bool) { + init(controller: ViewController, sourceNode: ASDisplayNode?, sourceRect: CGRect? = nil, passthroughTouches: Bool) { self.controller = controller self.sourceNode = sourceNode + self.sourceRect = sourceRect self.passthroughTouches = passthroughTouches } func transitionInfo() -> ContextControllerTakeControllerInfo? { let sourceNode = self.sourceNode + let sourceRect = self.sourceRect return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in if let sourceNode = sourceNode { - return (sourceNode, sourceNode.bounds) + return (sourceNode, sourceRect ?? sourceNode.bounds) } else { return nil } diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index 838237d59b..1d99e7f0e1 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -87,7 +87,7 @@ public final class ChatControllerInteraction { let openSearch: () -> Void let setupReply: (MessageId) -> Void let canSetupReply: (Message) -> ChatControllerInteractionSwipeAction - let navigateToFirstDateMessage: (Int32) -> Void + let navigateToFirstDateMessage: (Int32, Bool) -> Void let requestRedeliveryOfFailedMessages: (MessageId) -> Void let addContact: (String) -> Void let rateCall: (Message, CallId, Bool) -> Void @@ -181,7 +181,7 @@ public final class ChatControllerInteraction { openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> ChatControllerInteractionSwipeAction, - navigateToFirstDateMessage: @escaping(Int32) ->Void, + navigateToFirstDateMessage: @escaping(Int32, Bool) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId, Bool) -> Void, @@ -315,7 +315,7 @@ public final class ChatControllerInteraction { }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in }, canSetupReply: { _ in return .none - }, navigateToFirstDateMessage: { _ in + }, navigateToFirstDateMessage: { _, _ in }, requestRedeliveryOfFailedMessages: { _ in }, addContact: { _ in }, rateCall: { _, _, _ in diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index e0f430537a..79f70e97fd 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -951,8 +951,15 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(anchorIndex), anchorIndex: .message(anchorIndex), count: historyMessageCount, highlight: false), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) } } else { - if let subject = subject, case let .message(messageId, highlight, _) = subject { - strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60, highlight: highlight), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) + if let subject = subject, case let .message(messageSubject, highlight, _) = subject { + let initialSearchLocation: ChatHistoryInitialSearchLocation + switch messageSubject { + case let .id(id): + initialSearchLocation = .id(id) + case let .timestamp(timestamp): + initialSearchLocation = .index(MessageIndex(id: MessageId(peerId: strongSelf.chatLocation.peerId, namespace: Namespaces.Message.Cloud, id: 1), timestamp: timestamp)) + } + strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: initialSearchLocation, count: 60, highlight: highlight), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) } else if let subject = subject, case let .pinnedMessages(maybeMessageId) = subject, let messageId = maybeMessageId { strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60, highlight: true), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) } else if var chatHistoryLocation = strongSelf.chatHistoryLocationValue { @@ -1207,8 +1214,15 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } }) - if let subject = subject, case let .message(messageId, highlight, _) = subject { - self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60, highlight: highlight), id: 0) + if let subject = subject, case let .message(messageSubject, highlight, _) = subject { + let initialSearchLocation: ChatHistoryInitialSearchLocation + switch messageSubject { + case let .id(id): + initialSearchLocation = .id(id) + case let .timestamp(timestamp): + initialSearchLocation = .index(MessageIndex(id: MessageId(peerId: self.chatLocation.peerId, namespace: Namespaces.Message.Cloud, id: 1), timestamp: timestamp)) + } + self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: initialSearchLocation, count: 60, highlight: highlight), id: 0) } else if let subject = subject, case let .pinnedMessages(maybeMessageId) = subject, let messageId = maybeMessageId { self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60, highlight: true), id: 0) } else { diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 5fa2f2a777..e12c5e7da6 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -1520,7 +1520,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { for attribute in item.content.firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { openPeerId = attribute.messageId.peerId - navigate = .chat(textInputState: nil, subject: .message(id: attribute.messageId, highlight: true, timecode: nil), peekData: nil) + navigate = .chat(textInputState: nil, subject: .message(id: .id(attribute.messageId), highlight: true, timecode: nil), peekData: nil) } } diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index a55af7ee11..11e6b6bec4 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -2849,7 +2849,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode for attribute in item.content.firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { openPeerId = attribute.messageId.peerId - navigate = .chat(textInputState: nil, subject: .message(id: attribute.messageId, highlight: true, timecode: nil), peekData: nil) + navigate = .chat(textInputState: nil, subject: .message(id: .id(attribute.messageId), highlight: true, timecode: nil), peekData: nil) } } diff --git a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift b/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift index 16bf867fae..64f871ad5b 100644 --- a/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift +++ b/submodules/TelegramUI/Sources/ChatMessageDateHeader.swift @@ -26,9 +26,9 @@ final class ChatMessageDateHeader: ListViewItemHeader { let id: ListViewItemNode.HeaderId let presentationData: ChatPresentationData let context: AccountContext - let action: ((Int32) -> Void)? + let action: ((Int32, Bool) -> Void)? - init(timestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, context: AccountContext, action: ((Int32) -> Void)? = nil) { + init(timestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) { self.timestamp = timestamp self.scheduled = scheduled self.presentationData = presentationData @@ -117,9 +117,9 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { private var flashingOnScrolling = false private var stickDistanceFactor: CGFloat = 0.0 - private var action: ((Int32) -> Void)? = nil + private var action: ((Int32, Bool) -> Void)? = nil - init(localTimestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, context: AccountContext, action: ((Int32) -> Void)? = nil) { + init(localTimestamp: Int32, scheduled: Bool, presentationData: ChatPresentationData, context: AccountContext, action: ((Int32, Bool) -> Void)? = nil) { self.presentationData = presentationData self.context = context @@ -309,7 +309,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode { @objc func tapGesture(_ recognizer: ListViewTapGestureRecognizer) { if case .ended = recognizer.state { - self.action?(self.localTimestamp) + self.action?(self.localTimestamp, self.stickDistanceFactor < 0.5) } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index 7fec802f35..94b2fd6e06 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift @@ -827,7 +827,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD for attribute in item.content.firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { openPeerId = attribute.messageId.peerId - navigate = .chat(textInputState: nil, subject: .message(id: attribute.messageId, highlight: true, timecode: nil), peekData: nil) + navigate = .chat(textInputState: nil, subject: .message(id: .id(attribute.messageId), highlight: true, timecode: nil), peekData: nil) } } diff --git a/submodules/TelegramUI/Sources/ChatMessageItem.swift b/submodules/TelegramUI/Sources/ChatMessageItem.swift index 9d392bbacc..8aa39fd243 100644 --- a/submodules/TelegramUI/Sources/ChatMessageItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageItem.swift @@ -328,14 +328,14 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible { isScheduledMessages = true } - self.dateHeader = ChatMessageDateHeader(timestamp: content.index.timestamp, scheduled: isScheduledMessages, presentationData: presentationData, context: context, action: { timestamp in + self.dateHeader = ChatMessageDateHeader(timestamp: content.index.timestamp, scheduled: isScheduledMessages, presentationData: presentationData, context: context, action: { timestamp, alreadyThere in var calendar = NSCalendar.current calendar.timeZone = TimeZone(abbreviation: "UTC")! let date = Date(timeIntervalSince1970: TimeInterval(timestamp)) let components = calendar.dateComponents([.year, .month, .day], from: date) if let date = calendar.date(from: components) { - controllerInteraction.navigateToFirstDateMessage(Int32(date.timeIntervalSince1970)) + controllerInteraction.navigateToFirstDateMessage(Int32(date.timeIntervalSince1970), alreadyThere) } }) diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index 2faae669fb..0cd36aa674 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -975,7 +975,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { for attribute in item.content.firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { openPeerId = attribute.messageId.peerId - navigate = .chat(textInputState: nil, subject: .message(id: attribute.messageId, highlight: true, timecode: nil), peekData: nil) + navigate = .chat(textInputState: nil, subject: .message(id: .id(attribute.messageId), highlight: true, timecode: nil), peekData: nil) } } diff --git a/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift index da47eac52d..1446db7a84 100644 --- a/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageWebpageBubbleContentNode.swift @@ -70,7 +70,7 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode { } else { var subject: ChatControllerSubject? if let messageId = adAttribute.messageId { - subject = .message(id: messageId, highlight: true, timecode: nil) + subject = .message(id: .id(messageId), highlight: true, timecode: nil) } navigationData = .chat(textInputState: nil, subject: subject, peekData: nil) } diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 35e7a1565c..2b4d58df4b 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -489,7 +489,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, setupReply: { _ in }, canSetupReply: { _ in return .none - }, navigateToFirstDateMessage: { _ in + }, navigateToFirstDateMessage: { _, _ in }, requestRedeliveryOfFailedMessages: { _ in }, addContact: { _ in }, rateCall: { _, _, _ in @@ -884,11 +884,11 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { break case let .channelMessage(peerId, messageId, timecode): if let navigationController = strongSelf.getNavigationController() { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: .message(id: messageId, highlight: true, timecode: timecode))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: .message(id: .id(messageId), highlight: true, timecode: timecode))) } case let .replyThreadMessage(replyThreadMessage, messageId): if let navigationController = strongSelf.getNavigationController() { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(replyThreadMessage), subject: .message(id: messageId, highlight: true, timecode: nil))) + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(replyThreadMessage), subject: .message(id: .id(messageId), highlight: true, timecode: nil))) } case let .stickerPack(name): let packReference: StickerPackReference = .name(name) diff --git a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift index 0dc977c6ab..9887415263 100644 --- a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift @@ -232,7 +232,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe switch item.content { case let .peer(messages, peer, _, _, _, _, _, _, _, _, _, _): 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)) + let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.peerId), subject: .message(id: .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: [])), gesture: gesture) presentInGlobalOverlay(contextController) diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index 5421794303..5cee1b10ba 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -118,7 +118,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in }, canSetupReply: { _ in return .none - }, navigateToFirstDateMessage: { _ in + }, navigateToFirstDateMessage: { _, _ in }, requestRedeliveryOfFailedMessages: { _ in }, addContact: { _ in }, rateCall: { _, _, _ in diff --git a/submodules/TelegramUI/Sources/NavigateToChatController.swift b/submodules/TelegramUI/Sources/NavigateToChatController.swift index eecca4707f..0987ce4a5f 100644 --- a/submodules/TelegramUI/Sources/NavigateToChatController.swift +++ b/submodules/TelegramUI/Sources/NavigateToChatController.swift @@ -20,16 +20,18 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam if let updateTextInputState = params.updateTextInputState { controller.updateTextInputState(updateTextInputState) } - if let subject = params.subject, case let .message(messageId, _, timecode) = subject { - let navigationController = params.navigationController - let animated = params.animated - controller.navigateToMessage(messageLocation: .id(messageId, timecode), animated: isFirst, completion: { [weak navigationController, weak controller] in - if let navigationController = navigationController, let controller = controller { - let _ = navigationController.popToViewController(controller, animated: animated) - } - }, customPresentProgress: { [weak navigationController] c, a in - (navigationController?.viewControllers.last as? ViewController)?.present(c, in: .window(.root), with: a) - }) + if let subject = params.subject, case let .message(messageSubject, _, timecode) = subject { + if case let .id(messageId) = messageSubject { + let navigationController = params.navigationController + let animated = params.animated + controller.navigateToMessage(messageLocation: .id(messageId, timecode), animated: isFirst, completion: { [weak navigationController, weak controller] in + if let navigationController = navigationController, let controller = controller { + let _ = navigationController.popToViewController(controller, animated: animated) + } + }, customPresentProgress: { [weak navigationController] c, a in + (navigationController?.viewControllers.last as? ViewController)?.present(c, in: .window(.root), with: a) + }) + } } else if params.scrollToEndIfExists && isFirst { controller.scrollToEndOfHistory() let _ = params.navigationController.popToViewController(controller, animated: params.animated) diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 0d28f3d603..d02cbb5a4e 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -103,7 +103,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur dismissInput() navigationController?.pushViewController(controller) case let .channelMessage(peerId, messageId, timecode): - openPeer(peerId, .chat(textInputState: nil, subject: .message(id: messageId, highlight: true, timecode: timecode), peekData: nil)) + openPeer(peerId, .chat(textInputState: nil, subject: .message(id: .id(messageId), highlight: true, timecode: timecode), peekData: nil)) case let .replyThreadMessage(replyThreadMessage, messageId): if let navigationController = navigationController { let _ = ChatControllerImpl.openMessageReplies(context: context, navigationController: navigationController, present: { c, a in diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 0218b233e2..6dfcfe7f04 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -110,7 +110,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu }, setupReply: { _ in }, canSetupReply: { _ in return .none - }, navigateToFirstDateMessage: { _ in + }, navigateToFirstDateMessage: { _, _ in }, requestRedeliveryOfFailedMessages: { _ in }, addContact: { _ in }, rateCall: { _, _, _ in @@ -186,7 +186,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu self.isGlobalSearch = false } - self.historyNode = ChatHistoryListNode(context: context, updatedPresentationData: (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: .peer(peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, source: source, subject: .message(id: initialMessageId, highlight: true, timecode: nil), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch)) + self.historyNode = ChatHistoryListNode(context: context, updatedPresentationData: (context.sharedContext.currentPresentationData.with({ $0 }), context.sharedContext.presentationData), chatLocation: .peer(peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, source: source, subject: .message(id: .id(initialMessageId), highlight: true, timecode: nil), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch)) self.historyNode.clipsToBounds = true super.init() @@ -528,7 +528,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu } let chatLocationContextHolder = Atomic(value: nil) - let historyNode = ChatHistoryListNode(context: self.context, updatedPresentationData: (self.context.sharedContext.currentPresentationData.with({ $0 }), self.context.sharedContext.presentationData), chatLocation: .peer(self.peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, subject: .message(id: messageId, highlight: true, timecode: nil), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch)) + let historyNode = ChatHistoryListNode(context: self.context, updatedPresentationData: (self.context.sharedContext.currentPresentationData.with({ $0 }), self.context.sharedContext.presentationData), chatLocation: .peer(self.peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, subject: .message(id: .id(messageId), highlight: true, timecode: nil), controllerInteraction: self.controllerInteraction, selectedMessages: .single(nil), mode: .list(search: false, reversed: self.currentIsReversed, displayHeaders: .none, hintLinks: false, isGlobalSearch: self.isGlobalSearch)) historyNode.clipsToBounds = true historyNode.preloadPages = true historyNode.stackFromBottom = true diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 50852c30ba..0acb979581 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1800,7 +1800,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate c.dismiss(completion: { if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { let currentPeerId = strongSelf.peerId - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(currentPeerId), subject: .message(id: message.id, highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(currentPeerId), subject: .message(id: .id(message.id), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: { var viewControllers = navigationController.viewControllers var indexesToRemove = Set() var keptCurrentChatController = false @@ -1946,7 +1946,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate c.dismiss(completion: { if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController { let currentPeerId = strongSelf.peerId - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(currentPeerId), subject: .message(id: message.id, highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: { + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(currentPeerId), subject: .message(id: .id(message.id), highlight: true, timecode: nil), keepStack: .always, useExisting: false, purposefulAction: { var viewControllers = navigationController.viewControllers var indexesToRemove = Set() var keptCurrentChatController = false @@ -2198,7 +2198,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }, setupReply: { _ in }, canSetupReply: { _ in return .none - }, navigateToFirstDateMessage: { _ in + }, navigateToFirstDateMessage: { _, _ in }, requestRedeliveryOfFailedMessages: { _ in }, addContact: { _ in }, rateCall: { _, _, _ in @@ -6249,68 +6249,77 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate var dismissCalendarScreen: (() -> Void)? - let calendarScreen = CalendarMessageScreen(context: self.context, peerId: self.peerId, calendarSource: calendarSource, initialTimestamp: initialTimestamp, navigateToDay: { [weak self] c, index in - guard let strongSelf = self else { - c.dismiss() - return - } - guard let pane = strongSelf.paneContainerNode.currentPane?.node as? PeerInfoVisualMediaPaneNode else { - c.dismiss() - return - } - - pane.scrollToItem(index: index) - - c.dismiss() - }, previewDay: { [weak self] index, sourceNode, sourceRect, gesture in - guard let strongSelf = self else { - return - } - - var items: [ContextMenuItem] = [] - - items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.SharedMedia_ViewInChat, icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) - }, action: { _, f in - f(.dismissWithoutContent) - dismissCalendarScreen?() - - guard let strongSelf = self, let controller = strongSelf.controller, let navigationController = controller.navigationController as? NavigationController else { + let calendarScreen = CalendarMessageScreen( + context: self.context, + peerId: self.peerId, + calendarSource: calendarSource, + initialTimestamp: initialTimestamp, + enableMessageRangeDeletion: false, + canNavigateToEmptyDays: false, + navigateToDay: { [weak self] c, index, _ in + guard let strongSelf = self else { + c.dismiss() + return + } + guard let pane = strongSelf.paneContainerNode.currentPane?.node as? PeerInfoVisualMediaPaneNode else { + c.dismiss() return } - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams( - navigationController: navigationController, - chatController: nil, - context: strongSelf.context, - chatLocation: .peer(strongSelf.peerId), - subject: .message(id: index.id, highlight: false, timecode: nil), - botStart: nil, - updateTextInputState: nil, - activateInput: false, - keepStack: .never, - useExisting: true, - purposefulAction: nil, - scrollToEndIfExists: false, - activateMessageSearch: nil, - peekData: nil, - peerNearbyData: nil, - reportReason: nil, - animated: true, - options: [], - parentGroupId: nil, - chatListFilter: nil, - changeColors: false, - completion: { _ in - } - )) - }))) + pane.scrollToItem(index: index) - let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(strongSelf.peerId), subject: .message(id: index.id, highlight: false, 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: sourceNode, sourceRect: sourceRect, passthroughTouches: true)), items: .single(ContextController.Items(items: items)), gesture: gesture) - strongSelf.controller?.presentInGlobalOverlay(contextController) - }) + c.dismiss() + }, + previewDay: { [weak self] _, index, sourceNode, sourceRect, gesture in + guard let strongSelf = self, let index = index else { + return + } + + var items: [ContextMenuItem] = [] + + items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.SharedMedia_ViewInChat, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/GoToMessage"), color: theme.contextMenu.primaryColor) + }, action: { _, f in + f(.dismissWithoutContent) + dismissCalendarScreen?() + + guard let strongSelf = self, let controller = strongSelf.controller, let navigationController = controller.navigationController as? NavigationController else { + return + } + + strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams( + navigationController: navigationController, + chatController: nil, + context: strongSelf.context, + chatLocation: .peer(strongSelf.peerId), + subject: .message(id: .id(index.id), highlight: false, timecode: nil), + botStart: nil, + updateTextInputState: nil, + activateInput: false, + keepStack: .never, + useExisting: true, + purposefulAction: nil, + scrollToEndIfExists: false, + activateMessageSearch: nil, + peekData: nil, + peerNearbyData: nil, + reportReason: nil, + animated: true, + options: [], + parentGroupId: nil, + chatListFilter: nil, + changeColors: false, + completion: { _ in + } + )) + }))) + + let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(strongSelf.peerId), subject: .message(id: .id(index.id), highlight: false, 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: sourceNode, sourceRect: sourceRect, passthroughTouches: true)), items: .single(ContextController.Items(items: items)), gesture: gesture) + strongSelf.controller?.presentInGlobalOverlay(contextController) + } + ) self.controller?.push(calendarScreen) dismissCalendarScreen = { [weak calendarScreen] in diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 9a5cc971c7..d45e8d58d0 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1255,7 +1255,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { }, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in }, canSetupReply: { _ in return .none - }, navigateToFirstDateMessage: { _ in + }, navigateToFirstDateMessage: { _, _ in }, requestRedeliveryOfFailedMessages: { _ in }, addContact: { _ in }, rateCall: { _, _, _ in diff --git a/submodules/TelegramUI/Sources/TextLinkHandling.swift b/submodules/TelegramUI/Sources/TextLinkHandling.swift index acfd0a2519..fe46336d3b 100644 --- a/submodules/TelegramUI/Sources/TextLinkHandling.swift +++ b/submodules/TelegramUI/Sources/TextLinkHandling.swift @@ -59,7 +59,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate openResolvedPeerImpl(peerId, navigation) case let .channelMessage(peerId, messageId, timecode): if let navigationController = controller.navigationController as? NavigationController { - context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: .message(id: messageId, highlight: true, timecode: timecode))) + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: .message(id: .id(messageId), highlight: true, timecode: timecode))) } case let .replyThreadMessage(replyThreadMessage, messageId): if let navigationController = controller.navigationController as? NavigationController { diff --git a/submodules/UrlHandling/Sources/UrlHandling.swift b/submodules/UrlHandling/Sources/UrlHandling.swift index 9793c9856a..4dfa6cf399 100644 --- a/submodules/UrlHandling/Sources/UrlHandling.swift +++ b/submodules/UrlHandling/Sources/UrlHandling.swift @@ -425,7 +425,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl) return .replyThreadMessage(replyThreadMessage: result, messageId: messageId) } } else { - return .single(.peer(foundPeer.id, .chat(textInputState: nil, subject: .message(id: messageId, highlight: true, timecode: timecode), peekData: nil))) + return .single(.peer(foundPeer.id, .chat(textInputState: nil, subject: .message(id: .id(messageId), highlight: true, timecode: timecode), peekData: nil))) } } else { return .single(.inaccessiblePeer)