mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 17:30:12 +00:00
Calendar
This commit is contained in:
parent
b5d8390a98
commit
03f696fd8f
@ -7032,3 +7032,5 @@ Sorry for the inconvenience.";
|
|||||||
"Themes.BuildOwn" = "Build Your Own Theme";
|
"Themes.BuildOwn" = "Build Your Own Theme";
|
||||||
"Themes.EditCurrentTheme" = "Edit Current Theme";
|
"Themes.EditCurrentTheme" = "Edit Current Theme";
|
||||||
"Themes.CreateNewTheme" = "Create a New Theme";
|
"Themes.CreateNewTheme" = "Create a New Theme";
|
||||||
|
|
||||||
|
"Chat.JumpToDate" = "Jump to Date";
|
||||||
|
|||||||
@ -364,6 +364,11 @@ public struct ChatTextInputStateText: Codable, Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum ChatControllerSubject: Equatable {
|
public enum ChatControllerSubject: Equatable {
|
||||||
|
public enum MessageSubject: Equatable {
|
||||||
|
case id(MessageId)
|
||||||
|
case timestamp(Int32)
|
||||||
|
}
|
||||||
|
|
||||||
public struct ForwardOptions: Equatable {
|
public struct ForwardOptions: Equatable {
|
||||||
public let hideNames: Bool
|
public let hideNames: Bool
|
||||||
public let hideCaptions: 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 scheduledMessages
|
||||||
case pinnedMessages(id: EngineMessage.Id?)
|
case pinnedMessages(id: EngineMessage.Id?)
|
||||||
case forwardedMessages(ids: [EngineMessage.Id], options: Signal<ForwardOptions, NoError>)
|
case forwardedMessages(ids: [EngineMessage.Id], options: Signal<ForwardOptions, NoError>)
|
||||||
|
|||||||
@ -364,6 +364,7 @@ private final class DayComponent: Component {
|
|||||||
let isEnabled: Bool
|
let isEnabled: Bool
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
|
let timestamp: Int32
|
||||||
let media: DayMedia?
|
let media: DayMedia?
|
||||||
let selection: DaySelection
|
let selection: DaySelection
|
||||||
let isSelecting: Bool
|
let isSelecting: Bool
|
||||||
@ -375,6 +376,7 @@ private final class DayComponent: Component {
|
|||||||
isEnabled: Bool,
|
isEnabled: Bool,
|
||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
|
timestamp: Int32,
|
||||||
media: DayMedia?,
|
media: DayMedia?,
|
||||||
selection: DaySelection,
|
selection: DaySelection,
|
||||||
isSelecting: Bool,
|
isSelecting: Bool,
|
||||||
@ -385,6 +387,7 @@ private final class DayComponent: Component {
|
|||||||
self.isEnabled = isEnabled
|
self.isEnabled = isEnabled
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.context = context
|
self.context = context
|
||||||
|
self.timestamp = timestamp
|
||||||
self.media = media
|
self.media = media
|
||||||
self.selection = selection
|
self.selection = selection
|
||||||
self.isSelecting = isSelecting
|
self.isSelecting = isSelecting
|
||||||
@ -410,6 +413,9 @@ private final class DayComponent: Component {
|
|||||||
if lhs.media != rhs.media {
|
if lhs.media != rhs.media {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.timestamp != rhs.timestamp {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.selection != rhs.selection {
|
if lhs.selection != rhs.selection {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -430,6 +436,7 @@ private final class DayComponent: Component {
|
|||||||
private var action: (() -> Void)?
|
private var action: (() -> Void)?
|
||||||
private var currentMedia: DayMedia?
|
private var currentMedia: DayMedia?
|
||||||
|
|
||||||
|
private(set) var timestamp: Int32?
|
||||||
private(set) var index: MessageIndex?
|
private(set) var index: MessageIndex?
|
||||||
private var isHighlightingEnabled: Bool = false
|
private var isHighlightingEnabled: Bool = false
|
||||||
|
|
||||||
@ -473,6 +480,7 @@ private final class DayComponent: Component {
|
|||||||
let isFirstTime = self.action == nil
|
let isFirstTime = self.action == nil
|
||||||
|
|
||||||
self.action = component.action
|
self.action = component.action
|
||||||
|
self.timestamp = component.timestamp
|
||||||
self.index = component.media?.message.index
|
self.index = component.media?.message.index
|
||||||
self.isHighlightingEnabled = component.isEnabled && component.media != nil && !component.isSelecting
|
self.isHighlightingEnabled = component.isEnabled && component.media != nil && !component.isSelecting
|
||||||
|
|
||||||
@ -745,6 +753,7 @@ private final class MonthComponent: CombinedComponent {
|
|||||||
isEnabled: isEnabled,
|
isEnabled: isEnabled,
|
||||||
theme: context.component.theme,
|
theme: context.component.theme,
|
||||||
context: context.component.context,
|
context: context.component.context,
|
||||||
|
timestamp: dayTimestamp,
|
||||||
media: context.component.model.mediaByDay[index],
|
media: context.component.model.mediaByDay[index],
|
||||||
selection: daySelection,
|
selection: daySelection,
|
||||||
isSelecting: context.component.selectedDays != nil,
|
isSelecting: context.component.selectedDays != nil,
|
||||||
@ -959,8 +968,10 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
private let initialTimestamp: Int32
|
private let initialTimestamp: Int32
|
||||||
private let navigateToOffset: (Int) -> Void
|
private let enableMessageRangeDeletion: Bool
|
||||||
private let previewDay: (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void
|
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 presentationData: PresentationData
|
||||||
private var scrollView: Scroller
|
private var scrollView: Scroller
|
||||||
@ -988,11 +999,23 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
|
|
||||||
private var ignoreContentOffset: Bool = false
|
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.controller = controller
|
||||||
self.context = context
|
self.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.initialTimestamp = initialTimestamp
|
self.initialTimestamp = initialTimestamp
|
||||||
|
self.enableMessageRangeDeletion = enableMessageRangeDeletion
|
||||||
|
self.canNavigateToEmptyDays = canNavigateToEmptyDays
|
||||||
self.calendarSource = calendarSource
|
self.calendarSource = calendarSource
|
||||||
self.navigateToOffset = navigateToOffset
|
self.navigateToOffset = navigateToOffset
|
||||||
self.previewDay = previewDay
|
self.previewDay = previewDay
|
||||||
@ -1086,8 +1109,11 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
currentGestureDayView.isUserInteractionEnabled = false
|
currentGestureDayView.isUserInteractionEnabled = false
|
||||||
currentGestureDayView.isUserInteractionEnabled = true
|
currentGestureDayView.isUserInteractionEnabled = true
|
||||||
|
|
||||||
if let index = currentGestureDayView.index {
|
if currentGestureDayView.index == nil && !strongSelf.canNavigateToEmptyDays {
|
||||||
strongSelf.previewDay(index, strongSelf, currentGestureDayView.convert(currentGestureDayView.bounds, to: strongSelf.view), gesture)
|
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) {
|
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
let isFirstLayout = self.validLayout == nil
|
let isFirstLayout = self.validLayout == nil
|
||||||
self.validLayout = (layout, navigationHeight)
|
self.validLayout = (layout, navigationHeight)
|
||||||
@ -1292,8 +1333,8 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
let dayTimestamp = firstDayTimestamp + 24 * 60 * 60 * Int32(day)
|
let dayTimestamp = firstDayTimestamp + 24 * 60 * 60 * Int32(day)
|
||||||
let nextDayTimestamp = dayTimestamp + 24 * 60 * 60
|
let nextDayTimestamp = dayTimestamp + 24 * 60 * 60
|
||||||
|
|
||||||
let minDayTimestamp = dayTimestamp - 24 * 60 * 60
|
let minDayTimestamp = dayTimestamp
|
||||||
let maxDayTimestamp = nextDayTimestamp - 24 * 60 * 60
|
let maxDayTimestamp = nextDayTimestamp
|
||||||
|
|
||||||
if dayRange.contains(dayTimestamp) {
|
if dayRange.contains(dayTimestamp) {
|
||||||
if let currentMinTimestamp = minTimestamp {
|
if let currentMinTimestamp = minTimestamp {
|
||||||
@ -1401,6 +1442,13 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
let _ = strongSelf.calendarSource.removeMessagesInRange(minTimestamp: minTimestampValue, maxTimestamp: maxTimestampValue, type: type, completion: {
|
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()
|
actionSheet?.dismissAnimated()
|
||||||
|
|
||||||
beginClear(.forEveryone)
|
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 {
|
if let canClearForMyself = info.canClearForMyself {
|
||||||
@ -1588,7 +1624,7 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
for day in 0 ..< month.numberOfDays {
|
for day in 0 ..< month.numberOfDays {
|
||||||
let dayTimestamp = firstDayTimestamp + 24 * 60 * 60 * Int32(day)
|
let dayTimestamp = firstDayTimestamp + 24 * 60 * 60 * Int32(day)
|
||||||
if dayTimestamp == timestamp {
|
if dayTimestamp == timestamp {
|
||||||
if month.mediaByDay[day] != nil {
|
if month.mediaByDay[day] != nil || strongSelf.canNavigateToEmptyDays {
|
||||||
var offset = 0
|
var offset = 0
|
||||||
for key in calendarState.messagesByDay.keys.sorted(by: { $0 > $1 }) {
|
for key in calendarState.messagesByDay.keys.sorted(by: { $0 > $1 }) {
|
||||||
if key == dayTimestamp {
|
if key == dayTimestamp {
|
||||||
@ -1597,7 +1633,7 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
offset += item.count
|
offset += item.count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strongSelf.navigateToOffset(offset)
|
strongSelf.navigateToOffset(offset, dayTimestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
break outer
|
break outer
|
||||||
@ -1709,16 +1745,29 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
private let calendarSource: SparseMessageCalendar
|
private let calendarSource: SparseMessageCalendar
|
||||||
private let initialTimestamp: Int32
|
private let initialTimestamp: Int32
|
||||||
private let navigateToDay: (CalendarMessageScreen, Int) -> Void
|
private let enableMessageRangeDeletion: Bool
|
||||||
private let previewDay: (MessageIndex, ASDisplayNode, CGRect, ContextGesture) -> Void
|
private let canNavigateToEmptyDays: Bool
|
||||||
|
private let navigateToDay: (CalendarMessageScreen, Int, Int32) -> Void
|
||||||
|
private let previewDay: (Int32, MessageIndex?, ASDisplayNode, CGRect, ContextGesture) -> Void
|
||||||
|
|
||||||
private var presentationData: PresentationData
|
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.context = context
|
||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.calendarSource = calendarSource
|
self.calendarSource = calendarSource
|
||||||
self.initialTimestamp = initialTimestamp
|
self.initialTimestamp = initialTimestamp
|
||||||
|
self.enableMessageRangeDeletion = enableMessageRangeDeletion
|
||||||
|
self.canNavigateToEmptyDays = canNavigateToEmptyDays
|
||||||
self.navigateToDay = navigateToDay
|
self.navigateToDay = navigateToDay
|
||||||
self.previewDay = previewDay
|
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.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)
|
self.navigationItem.setTitle(self.presentationData.strings.MessageCalendar_Title, animated: false)
|
||||||
|
|
||||||
/*if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.SecretChat {
|
if self.enableMessageRangeDeletion {
|
||||||
self.navigationItem.setRightBarButton(UIBarButtonItem(title: self.presentationData.strings.Common_Select, style: .plain, target: self, action: #selector(self.toggleSelectPressed)), 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init(coder aDecoder: NSCoder) {
|
required public init(coder aDecoder: NSCoder) {
|
||||||
@ -1745,6 +1796,10 @@ public final class CalendarMessageScreen: ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc fileprivate func toggleSelectPressed() {
|
@objc fileprivate func toggleSelectPressed() {
|
||||||
|
if !self.enableMessageRangeDeletion {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
self.node.toggleSelectionMode()
|
self.node.toggleSelectionMode()
|
||||||
|
|
||||||
if self.node.selectionState != nil {
|
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() {
|
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
|
self.displayNode = Node(
|
||||||
guard let strongSelf = self else {
|
controller: self,
|
||||||
return
|
context: self.context,
|
||||||
}
|
peerId: self.peerId,
|
||||||
strongSelf.navigateToDay(strongSelf, index)
|
calendarSource: self.calendarSource,
|
||||||
}, previewDay: self.previewDay)
|
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()
|
self.displayNodeDidLoad()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -691,7 +691,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass {
|
if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass {
|
||||||
scrollToEndIfExists = true
|
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 {
|
if deactivateOnAction {
|
||||||
self?.deactivateSearch(animated: false)
|
self?.deactivateSearch(animated: false)
|
||||||
}
|
}
|
||||||
@ -861,7 +861,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
} else {
|
} else {
|
||||||
var subject: ChatControllerSubject?
|
var subject: ChatControllerSubject?
|
||||||
if case let .search(messageId) = source, let id = messageId {
|
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))
|
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)
|
chatController.canReadHistory.set(false)
|
||||||
|
|||||||
@ -56,7 +56,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
|||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.openMessageFromSearchDisposable.set((storedMessageFromSearchPeer(account: strongSelf.context.account, peer: peer._asPeer()) |> deliverOnMainQueue).start(next: { actualPeerId in
|
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 {
|
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)
|
strongSelf.controllerNode.listNode.clearHighlightAnimated(true)
|
||||||
|
|||||||
@ -1119,7 +1119,7 @@ public final class SparseItemGrid: ASDisplayNode {
|
|||||||
let previousProgress = self.currentProgress
|
let previousProgress = self.currentProgress
|
||||||
self.currentProgress = progress
|
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) {
|
if let fromItem = self.fromViewport.anchorItem(at: fixedAnchorPoint), let fromFrame = self.fromViewport.frameForItem(at: fromItem.index) {
|
||||||
fromAnchorFrame.origin.y = fromFrame.midY
|
fromAnchorFrame.origin.y = fromFrame.midY
|
||||||
|
|||||||
@ -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
|
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: {
|
c.dismiss(completion: {
|
||||||
if let navigationController = controller?.navigationController as? NavigationController {
|
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)))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})))
|
})))
|
||||||
|
|||||||
@ -263,7 +263,7 @@ public func messageStatsController(context: AccountContext, messageId: MessageId
|
|||||||
}
|
}
|
||||||
navigateToMessageImpl = { [weak controller] messageId in
|
navigateToMessageImpl = { [weak controller] messageId in
|
||||||
if let navigationController = controller?.navigationController as? NavigationController {
|
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
|
return controller
|
||||||
|
|||||||
@ -758,7 +758,7 @@ final class AuthorizedApplicationContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let navigateToMessage = {
|
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 {
|
if chatIsVisible {
|
||||||
@ -837,7 +837,7 @@ final class AuthorizedApplicationContext {
|
|||||||
|
|
||||||
if visiblePeerId != peerId || messageId != nil {
|
if visiblePeerId != peerId || messageId != nil {
|
||||||
if self.rootController.rootTabController != 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 {
|
} else {
|
||||||
self.scheduledOpenChatWithPeerId = (peerId, messageId, activateInput)
|
self.scheduledOpenChatWithPeerId = (peerId, messageId, activateInput)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -63,6 +63,7 @@ import Speak
|
|||||||
import UniversalMediaPlayer
|
import UniversalMediaPlayer
|
||||||
import WallpaperBackgroundNode
|
import WallpaperBackgroundNode
|
||||||
import ChatListUI
|
import ChatListUI
|
||||||
|
import CalendarMessageScreen
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
import os.signpost
|
import os.signpost
|
||||||
@ -2100,16 +2101,20 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return .none
|
return .none
|
||||||
}, navigateToFirstDateMessage: { [weak self] timestamp in
|
}, navigateToFirstDateMessage: { [weak self] timestamp, alreadyThere in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch strongSelf.chatLocation {
|
switch strongSelf.chatLocation {
|
||||||
case let .peer(peerId):
|
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)
|
if alreadyThere {
|
||||||
case let .replyThread(replyThreadMessage):
|
strongSelf.openCalendarSearch(timestamp: timestamp)
|
||||||
let peerId = replyThreadMessage.messageId.peerId
|
} 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)
|
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
|
}, requestRedeliveryOfFailedMessages: { [weak self] id in
|
||||||
guard let strongSelf = self else {
|
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
|
self.chatDisplayNode.historyNode.scrolledToIndex = { [weak self] toIndex, initial in
|
||||||
if let strongSelf = self, case let .message(index) = toIndex {
|
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)
|
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 {
|
} else if let controllerInteraction = strongSelf.controllerInteraction {
|
||||||
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(index.id) {
|
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(index.id) {
|
||||||
@ -6076,37 +6081,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, openCalendarSearch: { [weak self] in
|
}, openCalendarSearch: { [weak self] in
|
||||||
if let strongSelf = self {
|
self?.openCalendarSearch(timestamp: Int32(Date().timeIntervalSince1970))
|
||||||
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))
|
|
||||||
}
|
|
||||||
}, toggleMembersSearch: { [weak self] value in
|
}, toggleMembersSearch: { [weak self] value in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
|
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { state in
|
||||||
@ -7288,7 +7263,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let navigationController = strongSelf.effectiveNavigationController {
|
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))
|
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(replyThreadResult), subject: subject, keepStack: .always))
|
||||||
}
|
}
|
||||||
}, activatePinnedListPreview: { [weak self] node, gesture in
|
}, activatePinnedListPreview: { [weak self] node, gesture in
|
||||||
@ -11309,6 +11284,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) {
|
private func openMessageReplies(messageId: MessageId, displayProgressInMessage: MessageId?, isChannelPost: Bool, atMessage atMessageId: MessageId?, displayModalProgress: Bool) {
|
||||||
guard let navigationController = self.navigationController as? NavigationController else {
|
guard let navigationController = self.navigationController as? NavigationController else {
|
||||||
return
|
return
|
||||||
@ -11382,9 +11478,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
let subject: ChatControllerSubject?
|
let subject: ChatControllerSubject?
|
||||||
if let atMessageId = atMessageId {
|
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 {
|
} 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 {
|
} else {
|
||||||
subject = nil
|
subject = nil
|
||||||
}
|
}
|
||||||
@ -11447,11 +11543,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
if isPinnedMessages, let messageId = messageLocation.messageId {
|
if isPinnedMessages, let messageId = messageLocation.messageId {
|
||||||
if let navigationController = self.effectiveNavigationController {
|
if let navigationController = self.effectiveNavigationController {
|
||||||
self.dismiss()
|
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)) {
|
} 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 {
|
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 {
|
} else if forceInCurrentChat {
|
||||||
if let _ = fromId, let fromIndex = fromIndex, rememberInStack {
|
if let _ = fromId, let fromIndex = fromIndex, rememberInStack {
|
||||||
@ -11613,7 +11709,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
completion?()
|
completion?()
|
||||||
} else {
|
} else {
|
||||||
if let navigationController = strongSelf.effectiveNavigationController {
|
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?()
|
completion?()
|
||||||
}
|
}
|
||||||
@ -11625,7 +11721,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
if let navigationController = self.effectiveNavigationController {
|
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?()
|
completion?()
|
||||||
}
|
}
|
||||||
@ -12399,8 +12495,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
switch navigation {
|
switch navigation {
|
||||||
case let .chat(_, subject, peekData):
|
case let .chat(_, subject, peekData):
|
||||||
if case .peer(peerId) = strongSelf.chatLocation {
|
if case .peer(peerId) = strongSelf.chatLocation {
|
||||||
if let subject = subject, case let .message(messageId, _, timecode) = subject {
|
if let subject = subject, case let .message(messageSubject, _, timecode) = subject {
|
||||||
strongSelf.navigateToMessage(from: sourceMessageId, to: .id(messageId, timecode))
|
if case let .id(messageId) = messageSubject {
|
||||||
|
strongSelf.navigateToMessage(from: sourceMessageId, to: .id(messageId, timecode))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if let navigationController = strongSelf.effectiveNavigationController {
|
} 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))
|
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 {
|
private final class ContextControllerContentSourceImpl: ContextControllerContentSource {
|
||||||
let controller: ViewController
|
let controller: ViewController
|
||||||
weak var sourceNode: ASDisplayNode?
|
weak var sourceNode: ASDisplayNode?
|
||||||
|
let sourceRect: CGRect?
|
||||||
|
|
||||||
let navigationController: NavigationController? = nil
|
let navigationController: NavigationController? = nil
|
||||||
|
|
||||||
let passthroughTouches: Bool
|
let passthroughTouches: Bool
|
||||||
|
|
||||||
init(controller: ViewController, sourceNode: ASDisplayNode?, passthroughTouches: Bool) {
|
init(controller: ViewController, sourceNode: ASDisplayNode?, sourceRect: CGRect? = nil, passthroughTouches: Bool) {
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.sourceNode = sourceNode
|
self.sourceNode = sourceNode
|
||||||
|
self.sourceRect = sourceRect
|
||||||
self.passthroughTouches = passthroughTouches
|
self.passthroughTouches = passthroughTouches
|
||||||
}
|
}
|
||||||
|
|
||||||
func transitionInfo() -> ContextControllerTakeControllerInfo? {
|
func transitionInfo() -> ContextControllerTakeControllerInfo? {
|
||||||
let sourceNode = self.sourceNode
|
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
|
return ContextControllerTakeControllerInfo(contentAreaInScreenSpace: CGRect(origin: CGPoint(), size: CGSize(width: 10.0, height: 10.0)), sourceNode: { [weak sourceNode] in
|
||||||
if let sourceNode = sourceNode {
|
if let sourceNode = sourceNode {
|
||||||
return (sourceNode, sourceNode.bounds)
|
return (sourceNode, sourceRect ?? sourceNode.bounds)
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -87,7 +87,7 @@ public final class ChatControllerInteraction {
|
|||||||
let openSearch: () -> Void
|
let openSearch: () -> Void
|
||||||
let setupReply: (MessageId) -> Void
|
let setupReply: (MessageId) -> Void
|
||||||
let canSetupReply: (Message) -> ChatControllerInteractionSwipeAction
|
let canSetupReply: (Message) -> ChatControllerInteractionSwipeAction
|
||||||
let navigateToFirstDateMessage: (Int32) -> Void
|
let navigateToFirstDateMessage: (Int32, Bool) -> Void
|
||||||
let requestRedeliveryOfFailedMessages: (MessageId) -> Void
|
let requestRedeliveryOfFailedMessages: (MessageId) -> Void
|
||||||
let addContact: (String) -> Void
|
let addContact: (String) -> Void
|
||||||
let rateCall: (Message, CallId, Bool) -> Void
|
let rateCall: (Message, CallId, Bool) -> Void
|
||||||
@ -181,7 +181,7 @@ public final class ChatControllerInteraction {
|
|||||||
openSearch: @escaping () -> Void,
|
openSearch: @escaping () -> Void,
|
||||||
setupReply: @escaping (MessageId) -> Void,
|
setupReply: @escaping (MessageId) -> Void,
|
||||||
canSetupReply: @escaping (Message) -> ChatControllerInteractionSwipeAction,
|
canSetupReply: @escaping (Message) -> ChatControllerInteractionSwipeAction,
|
||||||
navigateToFirstDateMessage: @escaping(Int32) ->Void,
|
navigateToFirstDateMessage: @escaping(Int32, Bool) ->Void,
|
||||||
requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void,
|
requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void,
|
||||||
addContact: @escaping (String) -> Void,
|
addContact: @escaping (String) -> Void,
|
||||||
rateCall: @escaping (Message, CallId, Bool) -> 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
|
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
}, navigateToFirstDateMessage: { _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
}, rateCall: { _, _, _ in
|
}, rateCall: { _, _, _ in
|
||||||
|
|||||||
@ -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)
|
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(anchorIndex), anchorIndex: .message(anchorIndex), count: historyMessageCount, highlight: false), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let subject = subject, case let .message(messageId, highlight, _) = subject {
|
if let subject = subject, case let .message(messageSubject, highlight, _) = subject {
|
||||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60, highlight: highlight), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
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 {
|
} 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)
|
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 {
|
} 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 {
|
if let subject = subject, case let .message(messageSubject, highlight, _) = subject {
|
||||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60, highlight: highlight), id: 0)
|
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 {
|
} 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)
|
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60, highlight: true), id: 0)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1520,7 +1520,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
for attribute in item.content.firstMessage.attributes {
|
for attribute in item.content.firstMessage.attributes {
|
||||||
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||||
openPeerId = attribute.messageId.peerId
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2849,7 +2849,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
|||||||
for attribute in item.content.firstMessage.attributes {
|
for attribute in item.content.firstMessage.attributes {
|
||||||
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||||
openPeerId = attribute.messageId.peerId
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,9 +26,9 @@ final class ChatMessageDateHeader: ListViewItemHeader {
|
|||||||
let id: ListViewItemNode.HeaderId
|
let id: ListViewItemNode.HeaderId
|
||||||
let presentationData: ChatPresentationData
|
let presentationData: ChatPresentationData
|
||||||
let context: AccountContext
|
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.timestamp = timestamp
|
||||||
self.scheduled = scheduled
|
self.scheduled = scheduled
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
@ -117,9 +117,9 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
|
|
||||||
private var flashingOnScrolling = false
|
private var flashingOnScrolling = false
|
||||||
private var stickDistanceFactor: CGFloat = 0.0
|
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.presentationData = presentationData
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
@ -309,7 +309,7 @@ final class ChatMessageDateHeaderNode: ListViewItemHeaderNode {
|
|||||||
|
|
||||||
@objc func tapGesture(_ recognizer: ListViewTapGestureRecognizer) {
|
@objc func tapGesture(_ recognizer: ListViewTapGestureRecognizer) {
|
||||||
if case .ended = recognizer.state {
|
if case .ended = recognizer.state {
|
||||||
self.action?(self.localTimestamp)
|
self.action?(self.localTimestamp, self.stickDistanceFactor < 0.5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -827,7 +827,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
|||||||
for attribute in item.content.firstMessage.attributes {
|
for attribute in item.content.firstMessage.attributes {
|
||||||
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||||
openPeerId = attribute.messageId.peerId
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -328,14 +328,14 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
|||||||
isScheduledMessages = true
|
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
|
var calendar = NSCalendar.current
|
||||||
calendar.timeZone = TimeZone(abbreviation: "UTC")!
|
calendar.timeZone = TimeZone(abbreviation: "UTC")!
|
||||||
let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
|
let date = Date(timeIntervalSince1970: TimeInterval(timestamp))
|
||||||
let components = calendar.dateComponents([.year, .month, .day], from: date)
|
let components = calendar.dateComponents([.year, .month, .day], from: date)
|
||||||
|
|
||||||
if let date = calendar.date(from: components) {
|
if let date = calendar.date(from: components) {
|
||||||
controllerInteraction.navigateToFirstDateMessage(Int32(date.timeIntervalSince1970))
|
controllerInteraction.navigateToFirstDateMessage(Int32(date.timeIntervalSince1970), alreadyThere)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -975,7 +975,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
for attribute in item.content.firstMessage.attributes {
|
for attribute in item.content.firstMessage.attributes {
|
||||||
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||||
openPeerId = attribute.messageId.peerId
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,7 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
} else {
|
} else {
|
||||||
var subject: ChatControllerSubject?
|
var subject: ChatControllerSubject?
|
||||||
if let messageId = adAttribute.messageId {
|
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)
|
navigationData = .chat(textInputState: nil, subject: subject, peekData: nil)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -489,7 +489,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
}, setupReply: { _ in
|
}, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
}, navigateToFirstDateMessage: { _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
}, rateCall: { _, _, _ in
|
}, rateCall: { _, _, _ in
|
||||||
@ -884,11 +884,11 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
break
|
break
|
||||||
case let .channelMessage(peerId, messageId, timecode):
|
case let .channelMessage(peerId, messageId, timecode):
|
||||||
if let navigationController = strongSelf.getNavigationController() {
|
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):
|
case let .replyThreadMessage(replyThreadMessage, messageId):
|
||||||
if let navigationController = strongSelf.getNavigationController() {
|
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):
|
case let .stickerPack(name):
|
||||||
let packReference: StickerPackReference = .name(name)
|
let packReference: StickerPackReference = .name(name)
|
||||||
|
|||||||
@ -232,7 +232,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
|
|||||||
switch item.content {
|
switch item.content {
|
||||||
case let .peer(messages, peer, _, _, _, _, _, _, _, _, _, _):
|
case let .peer(messages, peer, _, _, _, _, _, _, _, _, _, _):
|
||||||
if let message = messages.first {
|
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)
|
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)
|
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)
|
presentInGlobalOverlay(contextController)
|
||||||
|
|||||||
@ -118,7 +118,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
|
|||||||
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
}, navigateToFirstDateMessage: { _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
}, rateCall: { _, _, _ in
|
}, rateCall: { _, _, _ in
|
||||||
|
|||||||
@ -20,16 +20,18 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||||||
if let updateTextInputState = params.updateTextInputState {
|
if let updateTextInputState = params.updateTextInputState {
|
||||||
controller.updateTextInputState(updateTextInputState)
|
controller.updateTextInputState(updateTextInputState)
|
||||||
}
|
}
|
||||||
if let subject = params.subject, case let .message(messageId, _, timecode) = subject {
|
if let subject = params.subject, case let .message(messageSubject, _, timecode) = subject {
|
||||||
let navigationController = params.navigationController
|
if case let .id(messageId) = messageSubject {
|
||||||
let animated = params.animated
|
let navigationController = params.navigationController
|
||||||
controller.navigateToMessage(messageLocation: .id(messageId, timecode), animated: isFirst, completion: { [weak navigationController, weak controller] in
|
let animated = params.animated
|
||||||
if let navigationController = navigationController, let controller = controller {
|
controller.navigateToMessage(messageLocation: .id(messageId, timecode), animated: isFirst, completion: { [weak navigationController, weak controller] in
|
||||||
let _ = navigationController.popToViewController(controller, animated: animated)
|
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)
|
}, customPresentProgress: { [weak navigationController] c, a in
|
||||||
})
|
(navigationController?.viewControllers.last as? ViewController)?.present(c, in: .window(.root), with: a)
|
||||||
|
})
|
||||||
|
}
|
||||||
} else if params.scrollToEndIfExists && isFirst {
|
} else if params.scrollToEndIfExists && isFirst {
|
||||||
controller.scrollToEndOfHistory()
|
controller.scrollToEndOfHistory()
|
||||||
let _ = params.navigationController.popToViewController(controller, animated: params.animated)
|
let _ = params.navigationController.popToViewController(controller, animated: params.animated)
|
||||||
|
|||||||
@ -103,7 +103,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
|||||||
dismissInput()
|
dismissInput()
|
||||||
navigationController?.pushViewController(controller)
|
navigationController?.pushViewController(controller)
|
||||||
case let .channelMessage(peerId, messageId, timecode):
|
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):
|
case let .replyThreadMessage(replyThreadMessage, messageId):
|
||||||
if let navigationController = navigationController {
|
if let navigationController = navigationController {
|
||||||
let _ = ChatControllerImpl.openMessageReplies(context: context, navigationController: navigationController, present: { c, a in
|
let _ = ChatControllerImpl.openMessageReplies(context: context, navigationController: navigationController, present: { c, a in
|
||||||
|
|||||||
@ -110,7 +110,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}, setupReply: { _ in
|
}, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
}, navigateToFirstDateMessage: { _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
}, rateCall: { _, _, _ in
|
}, rateCall: { _, _, _ in
|
||||||
@ -186,7 +186,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
self.isGlobalSearch = false
|
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
|
self.historyNode.clipsToBounds = true
|
||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
@ -528,7 +528,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}
|
}
|
||||||
|
|
||||||
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(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.clipsToBounds = true
|
||||||
historyNode.preloadPages = true
|
historyNode.preloadPages = true
|
||||||
historyNode.stackFromBottom = true
|
historyNode.stackFromBottom = true
|
||||||
|
|||||||
@ -1800,7 +1800,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
c.dismiss(completion: {
|
c.dismiss(completion: {
|
||||||
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
|
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
|
||||||
let currentPeerId = strongSelf.peerId
|
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 viewControllers = navigationController.viewControllers
|
||||||
var indexesToRemove = Set<Int>()
|
var indexesToRemove = Set<Int>()
|
||||||
var keptCurrentChatController = false
|
var keptCurrentChatController = false
|
||||||
@ -1946,7 +1946,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
c.dismiss(completion: {
|
c.dismiss(completion: {
|
||||||
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
|
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
|
||||||
let currentPeerId = strongSelf.peerId
|
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 viewControllers = navigationController.viewControllers
|
||||||
var indexesToRemove = Set<Int>()
|
var indexesToRemove = Set<Int>()
|
||||||
var keptCurrentChatController = false
|
var keptCurrentChatController = false
|
||||||
@ -2198,7 +2198,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
}, setupReply: { _ in
|
}, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
}, navigateToFirstDateMessage: { _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
}, rateCall: { _, _, _ in
|
}, rateCall: { _, _, _ in
|
||||||
@ -6249,68 +6249,77 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
|
|
||||||
var dismissCalendarScreen: (() -> Void)?
|
var dismissCalendarScreen: (() -> Void)?
|
||||||
|
|
||||||
let calendarScreen = CalendarMessageScreen(context: self.context, peerId: self.peerId, calendarSource: calendarSource, initialTimestamp: initialTimestamp, navigateToDay: { [weak self] c, index in
|
let calendarScreen = CalendarMessageScreen(
|
||||||
guard let strongSelf = self else {
|
context: self.context,
|
||||||
c.dismiss()
|
peerId: self.peerId,
|
||||||
return
|
calendarSource: calendarSource,
|
||||||
}
|
initialTimestamp: initialTimestamp,
|
||||||
guard let pane = strongSelf.paneContainerNode.currentPane?.node as? PeerInfoVisualMediaPaneNode else {
|
enableMessageRangeDeletion: false,
|
||||||
c.dismiss()
|
canNavigateToEmptyDays: false,
|
||||||
return
|
navigateToDay: { [weak self] c, index, _ in
|
||||||
}
|
guard let strongSelf = self else {
|
||||||
|
c.dismiss()
|
||||||
pane.scrollToItem(index: index)
|
return
|
||||||
|
}
|
||||||
c.dismiss()
|
guard let pane = strongSelf.paneContainerNode.currentPane?.node as? PeerInfoVisualMediaPaneNode else {
|
||||||
}, previewDay: { [weak self] index, sourceNode, sourceRect, gesture in
|
c.dismiss()
|
||||||
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 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
pane.scrollToItem(index: index)
|
||||||
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
|
|
||||||
}
|
|
||||||
))
|
|
||||||
})))
|
|
||||||
|
|
||||||
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))
|
c.dismiss()
|
||||||
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)
|
previewDay: { [weak self] _, index, sourceNode, sourceRect, gesture in
|
||||||
strongSelf.controller?.presentInGlobalOverlay(contextController)
|
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)
|
self.controller?.push(calendarScreen)
|
||||||
dismissCalendarScreen = { [weak calendarScreen] in
|
dismissCalendarScreen = { [weak calendarScreen] in
|
||||||
|
|||||||
@ -1255,7 +1255,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
}, navigateToFirstDateMessage: { _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
}, rateCall: { _, _, _ in
|
}, rateCall: { _, _, _ in
|
||||||
|
|||||||
@ -59,7 +59,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
|
|||||||
openResolvedPeerImpl(peerId, navigation)
|
openResolvedPeerImpl(peerId, navigation)
|
||||||
case let .channelMessage(peerId, messageId, timecode):
|
case let .channelMessage(peerId, messageId, timecode):
|
||||||
if let navigationController = controller.navigationController as? NavigationController {
|
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):
|
case let .replyThreadMessage(replyThreadMessage, messageId):
|
||||||
if let navigationController = controller.navigationController as? NavigationController {
|
if let navigationController = controller.navigationController as? NavigationController {
|
||||||
|
|||||||
@ -425,7 +425,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||||||
return .replyThreadMessage(replyThreadMessage: result, messageId: messageId)
|
return .replyThreadMessage(replyThreadMessage: result, messageId: messageId)
|
||||||
}
|
}
|
||||||
} else {
|
} 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 {
|
} else {
|
||||||
return .single(.inaccessiblePeer)
|
return .single(.inaccessiblePeer)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user