mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Support links for video timecodes
This commit is contained in:
parent
d4f1eedc3c
commit
ad98e74477
@ -171,7 +171,7 @@ public enum ResolvedUrl {
|
||||
case inaccessiblePeer
|
||||
case botStart(peerId: PeerId, payload: String)
|
||||
case groupBotStart(peerId: PeerId, payload: String)
|
||||
case channelMessage(peerId: PeerId, messageId: MessageId)
|
||||
case channelMessage(peerId: PeerId, messageId: MessageId, timecode: Double?)
|
||||
case replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage, messageId: MessageId)
|
||||
case stickerPack(name: String)
|
||||
case instantView(TelegramMediaWebpage, String?)
|
||||
|
@ -339,7 +339,7 @@ public struct ChatTextInputStateText: PostboxCoding, Equatable {
|
||||
}
|
||||
|
||||
public enum ChatControllerSubject: Equatable {
|
||||
case message(id: MessageId, highlight: Bool)
|
||||
case message(id: MessageId, highlight: Bool, timecode: Double?)
|
||||
case scheduledMessages
|
||||
case pinnedMessages(id: MessageId?)
|
||||
}
|
||||
|
@ -692,7 +692,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), purposefulAction: {
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), subject: .message(id: messageId, highlight: true, timecode: nil), purposefulAction: {
|
||||
if deactivateOnAction {
|
||||
self?.deactivateSearch(animated: false)
|
||||
}
|
||||
@ -862,7 +862,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)
|
||||
subject = .message(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)
|
||||
|
@ -965,7 +965,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
||||
let resolvedMessage = .single(nil)
|
||||
|> then(context.sharedContext.resolveUrl(context: context, peerId: nil, url: finalQuery, skipUrlAuth: true)
|
||||
|> mapToSignal { resolvedUrl -> Signal<Message?, NoError> in
|
||||
if case let .channelMessage(_, messageId) = resolvedUrl {
|
||||
if case let .channelMessage(_, messageId, _) = resolvedUrl {
|
||||
return context.engine.messages.downloadMessage(messageId: messageId)
|
||||
} else {
|
||||
return .single(nil)
|
||||
|
@ -57,7 +57,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
||||
if let strongSelf = self {
|
||||
strongSelf.openMessageFromSearchDisposable.set((storedMessageFromSearchPeer(account: strongSelf.context.account, peer: peer) |> 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) : nil, keepStack: .always))
|
||||
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.controllerNode.listNode.clearHighlightAnimated(true)
|
||||
|
@ -518,7 +518,7 @@ public func channelStatsController(context: AccountContext, peerId: PeerId, cach
|
||||
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)))
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: .message(id: messageId, highlight: true, timecode: nil)))
|
||||
}
|
||||
})
|
||||
})))
|
||||
|
@ -264,7 +264,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), keepStack: .always, useExisting: false, purposefulAction: {}, peekData: nil))
|
||||
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))
|
||||
}
|
||||
}
|
||||
return controller
|
||||
|
@ -759,7 +759,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)))
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: strongSelf.rootController, context: strongSelf.context, chatLocation: .peer(messageId.peerId), subject: .message(id: messageId, highlight: true, timecode: nil)))
|
||||
}
|
||||
|
||||
if chatIsVisible {
|
||||
@ -838,7 +838,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) }, activateInput: activateInput))
|
||||
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))
|
||||
} else {
|
||||
self.scheduledOpenChatWithPeerId = (peerId, messageId, activateInput)
|
||||
}
|
||||
|
@ -107,13 +107,13 @@ private enum ChatRecordingActivity {
|
||||
}
|
||||
|
||||
public enum NavigateToMessageLocation {
|
||||
case id(MessageId)
|
||||
case id(MessageId, Double?)
|
||||
case index(MessageIndex)
|
||||
case upperBound(PeerId)
|
||||
|
||||
var messageId: MessageId? {
|
||||
switch self {
|
||||
case let .id(id):
|
||||
case let .id(id, _):
|
||||
return id
|
||||
case let .index(index):
|
||||
return index.id
|
||||
@ -124,7 +124,7 @@ public enum NavigateToMessageLocation {
|
||||
|
||||
var peerId: PeerId {
|
||||
switch self {
|
||||
case let .id(id):
|
||||
case let .id(id, _):
|
||||
return id.peerId
|
||||
case let .index(index):
|
||||
return index.id.peerId
|
||||
@ -572,7 +572,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
case .pinnedMessageUpdated:
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId))
|
||||
strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId, nil))
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -581,7 +581,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
case .gameScore:
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId))
|
||||
strongSelf.navigateToMessage(from: message.id, to: .id(attribute.messageId, nil))
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -997,9 +997,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}, openMessageContextActions: { message, node, rect, gesture in
|
||||
gesture?.cancel()
|
||||
}, navigateToMessage: { [weak self] fromId, id in
|
||||
self?.navigateToMessage(from: fromId, to: .id(id), forceInCurrentChat: fromId.peerId == id.peerId)
|
||||
self?.navigateToMessage(from: fromId, to: .id(id, nil), forceInCurrentChat: fromId.peerId == id.peerId)
|
||||
}, navigateToMessageStandalone: { [weak self] id in
|
||||
self?.navigateToMessage(from: nil, to: .id(id), forceInCurrentChat: false)
|
||||
self?.navigateToMessage(from: nil, to: .id(id, nil), forceInCurrentChat: false)
|
||||
}, tapMessage: nil, clickThroughMessage: { [weak self] in
|
||||
self?.chatDisplayNode.dismissInput()
|
||||
}, toggleMessagesSelection: { [weak self] ids, value in
|
||||
@ -1876,7 +1876,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
guard let message = message else {
|
||||
return
|
||||
}
|
||||
let context = strongSelf.context
|
||||
let chatPresentationInterfaceState = strongSelf.presentationInterfaceState
|
||||
let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData)
|
||||
|
||||
let isCopyLink: Bool
|
||||
if message.id.namespace == Namespaces.Message.Cloud, let _ = message.peers[message.id.peerId] as? TelegramChannel, !(message.media.first is TelegramMediaAction) {
|
||||
isCopyLink = true
|
||||
} else {
|
||||
isCopyLink = false
|
||||
}
|
||||
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
ActionSheetTextItem(title: text),
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in
|
||||
@ -1885,12 +1895,52 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongSelf.controllerInteraction?.seekToTimecode(message, timecode, true)
|
||||
}
|
||||
}),
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in
|
||||
ActionSheetButtonItem(title: isCopyLink ? strongSelf.presentationData.strings.Conversation_ContextMenuCopyLink : strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in
|
||||
actionSheet?.dismissAnimated()
|
||||
UIPasteboard.general.string = text
|
||||
|
||||
let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_TextCopied)
|
||||
self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
if isCopyLink, let channel = message.peers[message.id.peerId] as? TelegramChannel {
|
||||
var threadMessageId: MessageId?
|
||||
|
||||
if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation {
|
||||
threadMessageId = replyThreadMessage.messageId
|
||||
}
|
||||
let _ = (exportMessageLink(account: context.account, peerId: message.id.peerId, messageId: message.id, isThread: threadMessageId != nil)
|
||||
|> map { result -> String? in
|
||||
return result
|
||||
}
|
||||
|> deliverOnMainQueue).start(next: { link in
|
||||
if let link = link {
|
||||
UIPasteboard.general.string = link + "?t=\(Int32(timecode))"
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
var warnAboutPrivate = false
|
||||
if case .peer = chatPresentationInterfaceState.chatLocation {
|
||||
if channel.addressName == nil {
|
||||
warnAboutPrivate = true
|
||||
}
|
||||
}
|
||||
Queue.mainQueue().after(0.2, {
|
||||
let content: UndoOverlayContent
|
||||
if warnAboutPrivate {
|
||||
content = .linkCopied(text: presentationData.strings.Conversation_PrivateMessageLinkCopiedLong)
|
||||
} else {
|
||||
content = .linkCopied(text: presentationData.strings.Conversation_LinkCopied)
|
||||
}
|
||||
self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
})
|
||||
} else {
|
||||
UIPasteboard.general.string = text
|
||||
|
||||
let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_TextCopied)
|
||||
self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
UIPasteboard.general.string = text
|
||||
|
||||
let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_TextCopied)
|
||||
self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||
}
|
||||
})
|
||||
]), ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in
|
||||
@ -2664,7 +2714,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongSelf.openMessageReplies(messageId: threadMessageId, displayProgressInMessage: message.id, isChannelPost: true, atMessage: attribute.messageId, displayModalProgress: false)
|
||||
}
|
||||
} else {
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(attribute.messageId))
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(attribute.messageId, nil))
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -4558,7 +4608,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(messageId, _, _) = strongSelf.subject, initial, 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) {
|
||||
@ -4575,6 +4625,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
if case let .message(_, _, timecode) = strongSelf.subject, let timecode = timecode, initial {
|
||||
Queue.mainQueue().after(0.2) {
|
||||
strongSelf.controllerInteraction?.openMessage(message, .timecode(timecode))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4859,7 +4915,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.chatDisplayNode.navigateButtons.downPressed = { [weak self] in
|
||||
if let strongSelf = self, strongSelf.isNodeLoaded {
|
||||
if let messageId = strongSelf.historyNavigationStack.removeLast() {
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(messageId.id), rememberInStack: false)
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(messageId.id, nil), rememberInStack: false)
|
||||
} else {
|
||||
if case .known = strongSelf.chatDisplayNode.historyNode.visibleContentOffset() {
|
||||
strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||
@ -4882,7 +4938,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
switch result {
|
||||
case let .result(messageId):
|
||||
if let messageId = messageId {
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(messageId))
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(messageId, nil))
|
||||
}
|
||||
case .loading:
|
||||
break
|
||||
@ -5445,7 +5501,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let strongSelf = self {
|
||||
strongSelf.loadingMessage.set(.single(nil))
|
||||
if let messageId = messageId {
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(messageId), forceInCurrentChat: true)
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(messageId, nil), forceInCurrentChat: true)
|
||||
}
|
||||
}
|
||||
}))
|
||||
@ -5473,7 +5529,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
strongSelf.updateItemNodesSearchTextHighlightStates()
|
||||
}
|
||||
}, navigateToMessage: { [weak self] messageId, dropStack, forceInCurrentChat, statusSubject in
|
||||
self?.navigateToMessage(from: nil, to: .id(messageId), forceInCurrentChat: forceInCurrentChat, dropStack: dropStack, statusSubject: statusSubject)
|
||||
self?.navigateToMessage(from: nil, to: .id(messageId, nil), forceInCurrentChat: forceInCurrentChat, dropStack: dropStack, statusSubject: statusSubject)
|
||||
}, navigateToChat: { [weak self] peerId in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -6621,7 +6677,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
|
||||
if let navigationController = strongSelf.effectiveNavigationController {
|
||||
let subject: ChatControllerSubject? = sourceMessageId.flatMap { ChatControllerSubject.message(id: $0, highlight: true) }
|
||||
let subject: ChatControllerSubject? = sourceMessageId.flatMap { ChatControllerSubject.message(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
|
||||
@ -7084,7 +7140,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
}
|
||||
if let currentItem = currentItem?.id as? PeerMessagesMediaPlaylistItemId, let previousItem = previousItem?.id as? PeerMessagesMediaPlaylistItemId, previousItem.messageId.peerId == peerId, currentItem.messageId.peerId == peerId, currentItem.messageId != previousItem.messageId {
|
||||
if strongSelf.chatDisplayNode.historyNode.isMessageVisibleOnScreen(currentItem.messageId) {
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(currentItem.messageId), scrollPosition: .center(.bottom), rememberInStack: false, animated: true, completion: nil)
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(currentItem.messageId, nil), scrollPosition: .center(.bottom), rememberInStack: false, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10560,9 +10616,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
|
||||
let subject: ChatControllerSubject?
|
||||
if let atMessageId = atMessageId {
|
||||
subject = .message(id: atMessageId, highlight: true)
|
||||
subject = .message(id: atMessageId, highlight: true, timecode: nil)
|
||||
} else if let index = result.scrollToLowerBoundMessage {
|
||||
subject = .message(id: index.id, highlight: false)
|
||||
subject = .message(id: index.id, highlight: false, timecode: nil)
|
||||
} else {
|
||||
subject = nil
|
||||
}
|
||||
@ -10626,11 +10682,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), keepStack: .always))
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), subject: .message(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), keepStack: .always))
|
||||
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), subject: .message(id: messageId, highlight: true, timecode: nil), keepStack: .always))
|
||||
}
|
||||
} else if forceInCurrentChat {
|
||||
if let _ = fromId, let fromIndex = fromIndex, rememberInStack {
|
||||
@ -10652,13 +10708,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
self.messageIndexDisposable.set(nil)
|
||||
self.chatDisplayNode.historyNode.scrollToMessage(from: scrollFromIndex, to: message.index, animated: animated, scrollPosition: scrollPosition)
|
||||
completion?()
|
||||
|
||||
if case let .id(_, timecode) = messageLocation, let timecode = timecode {
|
||||
self.controllerInteraction?.openMessage(message, .timecode(timecode))
|
||||
}
|
||||
} else if case let .index(index) = messageLocation, index.id.id == 0, index.timestamp > 0, case .scheduledMessages = self.presentationInterfaceState.subject {
|
||||
self.chatDisplayNode.historyNode.scrollToMessage(from: scrollFromIndex, to: index, animated: animated, scrollPosition: scrollPosition)
|
||||
} else {
|
||||
self.loadingMessage.set(.single(statusSubject) |> delay(0.1, queue: .mainQueue()))
|
||||
let searchLocation: ChatHistoryInitialSearchLocation
|
||||
switch messageLocation {
|
||||
case let .id(id):
|
||||
case let .id(id, _):
|
||||
searchLocation = .id(id)
|
||||
case let .index(index):
|
||||
searchLocation = .index(index)
|
||||
@ -10751,7 +10811,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
||||
if let fromIndex = fromIndex {
|
||||
let searchLocation: ChatHistoryInitialSearchLocation
|
||||
switch messageLocation {
|
||||
case let .id(id):
|
||||
case let .id(id, _):
|
||||
searchLocation = .id(id)
|
||||
case let .index(index):
|
||||
searchLocation = .index(index)
|
||||
@ -10785,7 +10845,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) }))
|
||||
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) }))
|
||||
}
|
||||
completion?()
|
||||
}
|
||||
@ -10797,7 +10857,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) }))
|
||||
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) }))
|
||||
}
|
||||
completion?()
|
||||
}
|
||||
@ -11555,8 +11615,8 @@ 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, _) = subject {
|
||||
strongSelf.navigateToMessage(from: nil, to: .id(messageId))
|
||||
if let subject = subject, case let .message(messageId, _, timecode) = subject {
|
||||
strongSelf.navigateToMessage(from: nil, 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))
|
||||
|
@ -910,7 +910,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
|
||||
strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount, highlight: false), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0)
|
||||
} else {
|
||||
if let subject = subject, case let .message(messageId, highlight) = subject {
|
||||
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)
|
||||
} 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)
|
||||
@ -1088,7 +1088,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||
}
|
||||
})
|
||||
|
||||
if let subject = subject, case let .message(messageId, highlight) = subject {
|
||||
if let subject = subject, case let .message(messageId, highlight, _) = subject {
|
||||
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), 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)
|
||||
|
@ -1278,7 +1278,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), peekData: nil)
|
||||
navigate = .chat(textInputState: nil, subject: .message(id: attribute.messageId, highlight: true, timecode: nil), peekData: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3012,7 +3012,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), peekData: nil)
|
||||
navigate = .chat(textInputState: nil, subject: .message(id: attribute.messageId, highlight: true, timecode: nil), peekData: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -731,7 +731,7 @@ class ChatMessageInstantVideoItemNode: 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), peekData: nil)
|
||||
navigate = .chat(textInputState: nil, subject: .message(id: attribute.messageId, highlight: true, timecode: nil), peekData: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -884,7 +884,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), peekData: nil)
|
||||
navigate = .chat(textInputState: nil, subject: .message(id: attribute.messageId, highlight: true, timecode: nil), peekData: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -905,13 +905,13 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
||||
break
|
||||
case .groupBotStart:
|
||||
break
|
||||
case let .channelMessage(peerId, messageId):
|
||||
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)))
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: .message(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)))
|
||||
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .replyThread(replyThreadMessage), subject: .message(id: messageId, highlight: true, timecode: nil)))
|
||||
}
|
||||
case let .stickerPack(name):
|
||||
let packReference: StickerPackReference = .name(name)
|
||||
|
@ -205,7 +205,7 @@ class ChatSearchResultsControllerNode: ViewControllerTracingNode, UIScrollViewDe
|
||||
switch item.content {
|
||||
case let .peer(peer):
|
||||
if let message = peer.messages.first {
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.peer.peerId), subject: .message(id: message.id, highlight: true), botStart: nil, mode: .standard(previewing: true))
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(peer.peer.peerId), subject: .message(id: message.id, highlight: true, timecode: nil), botStart: nil, mode: .standard(previewing: true))
|
||||
chatController.canReadHistory.set(false)
|
||||
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node)), items: .single([]), reactionItems: [], gesture: gesture)
|
||||
presentInGlobalOverlay(contextController)
|
||||
|
@ -20,10 +20,10 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
||||
if let updateTextInputState = params.updateTextInputState {
|
||||
controller.updateTextInputState(updateTextInputState)
|
||||
}
|
||||
if let subject = params.subject, case let .message(messageId, _) = subject {
|
||||
if let subject = params.subject, case let .message(messageId, _, timecode) = subject {
|
||||
let navigationController = params.navigationController
|
||||
let animated = params.animated
|
||||
controller.navigateToMessage(messageLocation: .id(messageId), animated: isFirst, completion: { [weak navigationController, weak controller] in
|
||||
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)
|
||||
}
|
||||
|
@ -97,8 +97,8 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
||||
}
|
||||
dismissInput()
|
||||
navigationController?.pushViewController(controller)
|
||||
case let .channelMessage(peerId, messageId):
|
||||
openPeer(peerId, .chat(textInputState: nil, subject: .message(id: messageId, highlight: true), peekData: nil))
|
||||
case let .channelMessage(peerId, messageId, timecode):
|
||||
openPeer(peerId, .chat(textInputState: nil, subject: .message(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
|
||||
|
@ -187,7 +187,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
||||
self.isGlobalSearch = false
|
||||
}
|
||||
|
||||
self.historyNode = ChatHistoryListNode(context: context, chatLocation: .peer(peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, source: source, subject: .message(id: initialMessageId, highlight: true), 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, 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))
|
||||
|
||||
super.init()
|
||||
|
||||
@ -528,7 +528,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
||||
}
|
||||
|
||||
let chatLocationContextHolder = Atomic<ChatLocationContextHolder?>(value: nil)
|
||||
let historyNode = ChatHistoryListNode(context: self.context, chatLocation: .peer(self.peerId), chatLocationContextHolder: chatLocationContextHolder, tagMask: tagMask, subject: .message(id: messageId, highlight: true), 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, 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))
|
||||
historyNode.preloadPages = true
|
||||
historyNode.stackFromBottom = true
|
||||
historyNode.updateFloatingHeaderOffset = { [weak self] offset, _ in
|
||||
|
@ -1738,7 +1738,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
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), keepStack: .always, useExisting: false, purposefulAction: {
|
||||
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: {
|
||||
var viewControllers = navigationController.viewControllers
|
||||
var indexesToRemove = Set<Int>()
|
||||
var keptCurrentChatController = false
|
||||
@ -1884,7 +1884,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
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), keepStack: .always, useExisting: false, purposefulAction: {
|
||||
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: {
|
||||
var viewControllers = navigationController.viewControllers
|
||||
var indexesToRemove = Set<Int>()
|
||||
var keptCurrentChatController = false
|
||||
@ -2775,7 +2775,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
|
||||
if copyUsername, let username = user.username, !username.isEmpty {
|
||||
actions.append(ContextMenuAction(content: .text(title: strongSelf.presentationData.strings.Settings_CopyUsername, accessibilityLabel: strongSelf.presentationData.strings.Settings_CopyUsername), action: { [weak self] in
|
||||
UIPasteboard.general.string = username
|
||||
UIPasteboard.general.string = "@\(username)"
|
||||
|
||||
if let strongSelf = self {
|
||||
let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
@ -58,9 +58,9 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
|
||||
context.sharedContext.applicationBindings.openUrl(url)
|
||||
case let .peer(peerId, navigation):
|
||||
openResolvedPeerImpl(peerId, navigation)
|
||||
case let .channelMessage(peerId, messageId):
|
||||
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)))
|
||||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: .message(id: messageId, highlight: true, timecode: timecode)))
|
||||
}
|
||||
case let .replyThreadMessage(replyThreadMessage, messageId):
|
||||
if let navigationController = controller.navigationController as? NavigationController {
|
||||
|
@ -16,7 +16,7 @@ private let baseTelegraPhPaths = ["telegra.ph/", "te.legra.ph/", "graph.org/", "
|
||||
public enum ParsedInternalPeerUrlParameter {
|
||||
case botStart(String)
|
||||
case groupBotStart(String)
|
||||
case channelMessage(Int32)
|
||||
case channelMessage(Int32, Double?)
|
||||
case replyThread(Int32, Int32)
|
||||
case voiceChat(String?)
|
||||
}
|
||||
@ -24,7 +24,7 @@ public enum ParsedInternalPeerUrlParameter {
|
||||
public enum ParsedInternalUrl {
|
||||
case peerName(String, ParsedInternalPeerUrlParameter?)
|
||||
case peerId(PeerId)
|
||||
case privateMessage(messageId: MessageId, threadId: Int32?)
|
||||
case privateMessage(messageId: MessageId, threadId: Int32?, timecode: Double?)
|
||||
case stickerPack(String)
|
||||
case join(String)
|
||||
case localization(String)
|
||||
@ -281,37 +281,44 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
|
||||
} else if pathComponents.count == 3 && pathComponents[0] == "c" {
|
||||
if let channelId = Int32(pathComponents[1]), let messageId = Int32(pathComponents[2]) {
|
||||
var threadId: Int32?
|
||||
var timecode: Double?
|
||||
if let queryItems = components.queryItems {
|
||||
for queryItem in queryItems {
|
||||
if let value = queryItem.value {
|
||||
if queryItem.name == "thread" {
|
||||
if let intValue = Int32(value) {
|
||||
threadId = intValue
|
||||
break
|
||||
}
|
||||
} else if queryItem.name == "t" {
|
||||
if let doubleValue = Double(value) {
|
||||
timecode = doubleValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return .privateMessage(messageId: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt32Value(channelId)), namespace: Namespaces.Message.Cloud, id: messageId), threadId: threadId)
|
||||
return .privateMessage(messageId: MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt32Value(channelId)), namespace: Namespaces.Message.Cloud, id: messageId), threadId: threadId, timecode: timecode)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
} else if let value = Int32(pathComponents[1]) {
|
||||
var threadId: Int32?
|
||||
var commentId: Int32?
|
||||
var timecode: Double?
|
||||
if let queryItems = components.queryItems {
|
||||
for queryItem in queryItems {
|
||||
if let value = queryItem.value {
|
||||
if queryItem.name == "thread" {
|
||||
if let intValue = Int32(value) {
|
||||
threadId = intValue
|
||||
break
|
||||
}
|
||||
} else if queryItem.name == "comment" {
|
||||
if let intValue = Int32(value) {
|
||||
commentId = intValue
|
||||
break
|
||||
}
|
||||
} else if queryItem.name == "t" {
|
||||
if let doubleValue = Double(value) {
|
||||
timecode = doubleValue
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -322,7 +329,7 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? {
|
||||
} else if let commentId = commentId {
|
||||
return .peerName(peerName, .replyThread(value, commentId))
|
||||
} else {
|
||||
return .peerName(peerName, .channelMessage(value))
|
||||
return .peerName(peerName, .channelMessage(value, timecode))
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
@ -357,8 +364,8 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
return .single(.botStart(peerId: peer.id, payload: payload))
|
||||
case let .groupBotStart(payload):
|
||||
return .single(.groupBotStart(peerId: peer.id, payload: payload))
|
||||
case let .channelMessage(id):
|
||||
return .single(.channelMessage(peerId: peer.id, messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id)))
|
||||
case let .channelMessage(id, timecode):
|
||||
return .single(.channelMessage(peerId: peer.id, messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id), timecode: timecode))
|
||||
case let .replyThread(id, replyId):
|
||||
let replyThreadMessageId = MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: id)
|
||||
return fetchChannelReplyThreadMessage(account: context.account, messageId: replyThreadMessageId, atMessageId: nil)
|
||||
@ -368,7 +375,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
}
|
||||
|> map { result -> ResolvedUrl? in
|
||||
guard let result = result else {
|
||||
return .channelMessage(peerId: peer.id, messageId: replyThreadMessageId)
|
||||
return .channelMessage(peerId: peer.id, messageId: replyThreadMessageId, timecode: nil)
|
||||
}
|
||||
return .replyThreadMessage(replyThreadMessage: result, messageId: MessageId(peerId: result.messageId.peerId, namespace: Namespaces.Message.Cloud, id: replyId))
|
||||
}
|
||||
@ -397,7 +404,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
return .single(.inaccessiblePeer)
|
||||
}
|
||||
}
|
||||
case let .privateMessage(messageId, threadId):
|
||||
case let .privateMessage(messageId, threadId, timecode):
|
||||
return context.account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(messageId.peerId)
|
||||
}
|
||||
@ -420,12 +427,12 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
||||
}
|
||||
|> map { result -> ResolvedUrl? in
|
||||
guard let result = result else {
|
||||
return .channelMessage(peerId: foundPeer.id, messageId: replyThreadMessageId)
|
||||
return .channelMessage(peerId: foundPeer.id, messageId: replyThreadMessageId, timecode: timecode)
|
||||
}
|
||||
return .replyThreadMessage(replyThreadMessage: result, messageId: messageId)
|
||||
}
|
||||
} else {
|
||||
return .single(.peer(foundPeer.id, .chat(textInputState: nil, subject: .message(id: messageId, highlight: true), peekData: nil)))
|
||||
return .single(.peer(foundPeer.id, .chat(textInputState: nil, subject: .message(id: messageId, highlight: true, timecode: timecode), peekData: nil)))
|
||||
}
|
||||
} else {
|
||||
return .single(.inaccessiblePeer)
|
||||
|
@ -31,7 +31,7 @@ public func parseUrl(url: String, wasConcealed: Bool) -> (string: String, concea
|
||||
latin.insert(charactersIn: "a"..."z")
|
||||
latin.insert(charactersIn: "0"..."9")
|
||||
var punctuation = CharacterSet()
|
||||
punctuation.insert(charactersIn: ".-/+_")
|
||||
punctuation.insert(charactersIn: ".-/+_?=")
|
||||
var hasLatin = false
|
||||
var hasNonLatin = false
|
||||
for c in rawHost {
|
||||
|
Loading…
x
Reference in New Issue
Block a user