Scheduled Messages UI improvements

This commit is contained in:
Ilya Laktyushin 2019-08-21 02:05:10 +03:00
parent 4b6c54f84a
commit 263d78c1b3
31 changed files with 234 additions and 200 deletions

View File

@ -4609,8 +4609,11 @@ Any member of this group will be able to see messages in the channel.";
"ScheduledMessages.SendNow" = "Send Now"; "ScheduledMessages.SendNow" = "Send Now";
"ScheduledMessages.EditTime" = "Reschedule"; "ScheduledMessages.EditTime" = "Reschedule";
"ScheduledMessages.ClearAll" = "Clear All"; "ScheduledMessages.ClearAll" = "Clear All";
"ScheduledMessages.Delete" = "Delete"; "ScheduledMessages.ClearAllConfirmation" = "Clear Scheduled Messages";
"ScheduledMessages.Delete" = "Delete Scheduled Message";
"ScheduledMessages.DeleteMany" = "Delete Scheduled Messages";
"ScheduledMessages.EmptyPlaceholder" = "No scheduled messages here yet..."; "ScheduledMessages.EmptyPlaceholder" = "No scheduled messages here yet...";
"ScheduledMessages.BotActionUnavailable" = "This action will become available after the message is published.";
"Conversation.SendMessage.SetReminder" = "Set a Reminder"; "Conversation.SendMessage.SetReminder" = "Set a Reminder";
@ -4657,3 +4660,5 @@ Any member of this group will be able to see messages in the channel.";
"Appearance.ThemePreview.Chat.4.Text" = "Nearly missed the sunrise."; "Appearance.ThemePreview.Chat.4.Text" = "Nearly missed the sunrise.";
"GroupInfo.Permissions.SlowmodeValue.Off" = "Off"; "GroupInfo.Permissions.SlowmodeValue.Off" = "Off";
"Undo.ScheduledMessagesCleared" = "Scheduled messages cleared";

View File

@ -179,7 +179,7 @@ public final class NavigateToChatControllerParams {
public let chatController: ChatController? public let chatController: ChatController?
public let context: AccountContext public let context: AccountContext
public let chatLocation: ChatLocation public let chatLocation: ChatLocation
public let messageId: MessageId? public let subject: ChatControllerSubject?
public let botStart: ChatControllerInitialBotStart? public let botStart: ChatControllerInitialBotStart?
public let updateTextInputState: ChatTextInputState? public let updateTextInputState: ChatTextInputState?
public let activateInput: Bool public let activateInput: Bool
@ -191,12 +191,12 @@ public final class NavigateToChatControllerParams {
public let parentGroupId: PeerGroupId? public let parentGroupId: PeerGroupId?
public let completion: () -> Void public let completion: () -> Void
public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, messageId: MessageId? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) { public init(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, subject: ChatControllerSubject? = nil, botStart: ChatControllerInitialBotStart? = nil, updateTextInputState: ChatTextInputState? = nil, activateInput: Bool = false, keepStack: NavigateToChatKeepStack = .default, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) {
self.navigationController = navigationController self.navigationController = navigationController
self.chatController = chatController self.chatController = chatController
self.context = context self.context = context
self.chatLocation = chatLocation self.chatLocation = chatLocation
self.messageId = messageId self.subject = subject
self.botStart = botStart self.botStart = botStart
self.updateTextInputState = updateTextInputState self.updateTextInputState = updateTextInputState
self.activateInput = activateInput self.activateInput = activateInput

View File

@ -7,7 +7,7 @@ import SwiftSignalKit
public enum ChatControllerInitialBotStartBehavior { public enum ChatControllerInitialBotStartBehavior {
case interactive case interactive
case automatic(returnToPeerId: PeerId) case automatic(returnToPeerId: PeerId, scheduled: Bool)
} }
public struct ChatControllerInitialBotStart { public struct ChatControllerInitialBotStart {
@ -22,7 +22,7 @@ public struct ChatControllerInitialBotStart {
public enum ChatControllerInteractionNavigateToPeer { public enum ChatControllerInteractionNavigateToPeer {
case `default` case `default`
case chat(textInputState: ChatTextInputState?, messageId: MessageId?) case chat(textInputState: ChatTextInputState?, subject: ChatControllerSubject?)
case info case info
case withBotStartPayload(ChatControllerInitialBotStart) case withBotStartPayload(ChatControllerInitialBotStart)
} }

View File

@ -570,7 +570,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
return return
} }
let beginClear: (InteractiveMessagesDeletionType) -> Void = { type in let beginClear: (InteractiveHistoryClearingType) -> Void = { type in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -748,7 +748,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
} }
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), messageId: messageId, purposefulAction: { strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), subject: .message(messageId), purposefulAction: {
self?.deactivateSearch(animated: false) self?.deactivateSearch(animated: false)
}, scrollToEndIfExists: scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [])) }, scrollToEndIfExists: scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : []))
strongSelf.chatListDisplayNode.chatListNode.clearHighlightAnimated(true) strongSelf.chatListDisplayNode.chatListNode.clearHighlightAnimated(true)

View File

@ -53,7 +53,7 @@ public final class HashtagSearchController: TelegramBaseController {
if let strongSelf = self { if let strongSelf = self {
strongSelf.openMessageFromSearchDisposable.set((storedMessageFromSearchPeer(account: strongSelf.context.account, peer: peer) |> deliverOnMainQueue).start(next: { actualPeerId in 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 { if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), messageId: message.id.peerId == actualPeerId ? message.id : nil, keepStack: .always)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), subject: message.id.peerId == actualPeerId ? .message(message.id) : nil, keepStack: .always))
} }
})) }))
strongSelf.controllerNode.listNode.clearHighlightAnimated(true) strongSelf.controllerNode.listNode.clearHighlightAnimated(true)

View File

@ -1199,9 +1199,9 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate {
strongSelf.loadProgress.set(1.0) strongSelf.loadProgress.set(1.0)
strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.getNavigationController(), openPeer: { peerId, navigation in strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.getNavigationController(), openPeer: { peerId, navigation in
switch navigation { switch navigation {
case let .chat(_, messageId): case let .chat(_, subject):
if let navigationController = strongSelf.getNavigationController() { if let navigationController = strongSelf.getNavigationController() {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), messageId: messageId)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: subject))
} }
case let .withBotStartPayload(botStart): case let .withBotStartPayload(botStart):
if let navigationController = strongSelf.getNavigationController() { if let navigationController = strongSelf.getNavigationController() {

View File

@ -787,7 +787,7 @@ final class AuthorizedApplicationContext {
} }
let navigateToMessage = { let navigateToMessage = {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: strongSelf.rootController, context: strongSelf.context, chatLocation: .peer(messageId.peerId), messageId: messageId)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: strongSelf.rootController, context: strongSelf.context, chatLocation: .peer(messageId.peerId), subject: .message(messageId)))
} }
if chatIsVisible { if chatIsVisible {
@ -832,7 +832,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), messageId: messageId, activateInput: activateInput)) self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: .peer(peerId), subject: messageId.flatMap { .message($0) }, activateInput: activateInput))
} else { } else {
self.scheduledOperChatWithPeerId = (peerId, messageId, activateInput) self.scheduledOperChatWithPeerId = (peerId, messageId, activateInput)
} }

View File

@ -301,7 +301,7 @@ final class ChatBotInfoItemNode: ListViewItemNode {
case let .url(url, concealed): case let .url(url, concealed):
self.item?.controllerInteraction.openUrl(url, concealed, nil) self.item?.controllerInteraction.openUrl(url, concealed, nil)
case let .peerMention(peerId, _): case let .peerMention(peerId, _):
self.item?.controllerInteraction.openPeer(peerId, .chat(textInputState: nil, messageId: nil), nil) self.item?.controllerInteraction.openPeer(peerId, .chat(textInputState: nil, subject: nil), nil)
case let .textMention(name): case let .textMention(name):
self.item?.controllerInteraction.openPeerMention(name) self.item?.controllerInteraction.openPeerMention(name)
case let .botCommand(command): case let .botCommand(command):

View File

@ -198,7 +198,7 @@ final class ChatButtonKeyboardInputNode: ChatInputNode {
peerId = message.id.peerId peerId = message.id.peerId
} }
if let botPeer = botPeer, let addressName = botPeer.addressName { if let botPeer = botPeer, let addressName = botPeer.addressName {
self.controllerInteraction.openPeer(peerId, .chat(textInputState: ChatTextInputState(inputText: NSAttributedString(string: "@\(addressName) \(query)")), messageId: nil), nil) self.controllerInteraction.openPeer(peerId, .chat(textInputState: ChatTextInputState(inputText: NSAttributedString(string: "@\(addressName) \(query)")), subject: nil), nil)
} }
} }
case .payment: case .payment:

View File

@ -319,6 +319,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var isScheduledMessages = false var isScheduledMessages = false
if let subject = subject, case .scheduledMessages = subject { if let subject = subject, case .scheduledMessages = subject {
self.canReadHistory.set(false)
isScheduledMessages = true isScheduledMessages = true
} }
@ -588,6 +589,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState) else { guard let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState) else {
return return
} }
guard !strongSelf.presentationInterfaceState.isScheduledMessages else {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_BotActionUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
return
}
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
if let strongSelf = self { if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, {
@ -659,6 +664,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return true return true
}, requestMessageActionCallback: { [weak self] messageId, data, isGame in }, requestMessageActionCallback: { [weak self] messageId, data, isGame in
if let strongSelf = self { if let strongSelf = self {
guard !strongSelf.presentationInterfaceState.isScheduledMessages else {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_BotActionUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
return
}
if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) { if let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
return $0.updatedTitlePanelContext { return $0.updatedTitlePanelContext {
@ -728,6 +738,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
}, requestMessageActionUrlAuth: { [weak self] defaultUrl, messageId, buttonId in }, requestMessageActionUrlAuth: { [weak self] defaultUrl, messageId, buttonId in
if let strongSelf = self { if let strongSelf = self {
guard !strongSelf.presentationInterfaceState.isScheduledMessages else {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_BotActionUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
return
}
if let _ = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) { if let _ = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId) {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
return $0.updatedTitlePanelContext { return $0.updatedTitlePanelContext {
@ -845,10 +859,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
if let botStart = strongSelf.botStart, case let .automatic(returnToPeerId) = botStart.behavior { guard !strongSelf.presentationInterfaceState.isScheduledMessages else {
strongSelf.openPeer(peerId: returnToPeerId, navigation: .chat(textInputState: ChatTextInputState(inputText: NSAttributedString(string: inputString)), messageId: nil), fromMessage: nil) strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_BotActionUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
return
}
if let botStart = strongSelf.botStart, case let .automatic(returnToPeerId, scheduled) = botStart.behavior {
strongSelf.openPeer(peerId: returnToPeerId, navigation: .chat(textInputState: ChatTextInputState(inputText: NSAttributedString(string: inputString)), subject: scheduled ? .scheduledMessages : nil), fromMessage: nil)
} else { } else {
strongSelf.openPeer(peerId: peerId, navigation: .chat(textInputState: ChatTextInputState(inputText: NSAttributedString(string: inputString)), messageId: nil), fromMessage: nil) strongSelf.openPeer(peerId: peerId, navigation: .chat(textInputState: ChatTextInputState(inputText: NSAttributedString(string: inputString)), subject: nil), fromMessage: nil)
} }
}, openUrl: { [weak self] url, concealed, _ in }, openUrl: { [weak self] url, concealed, _ in
if let strongSelf = self { if let strongSelf = self {
@ -856,6 +874,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
}, shareCurrentLocation: { [weak self] in }, shareCurrentLocation: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
guard !strongSelf.presentationInterfaceState.isScheduledMessages else {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_BotActionUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
return
}
strongSelf.present(textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Conversation_ShareBotLocationConfirmationTitle, text: strongSelf.presentationData.strings.Conversation_ShareBotLocationConfirmation, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: { strongSelf.present(textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Conversation_ShareBotLocationConfirmationTitle, text: strongSelf.presentationData.strings.Conversation_ShareBotLocationConfirmation, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
if let strongSelf = self, let locationManager = strongSelf.context.sharedContext.locationManager { if let strongSelf = self, let locationManager = strongSelf.context.sharedContext.locationManager {
let _ = (currentLocationManagerCoordinate(manager: locationManager, timeout: 5.0) let _ = (currentLocationManagerCoordinate(manager: locationManager, timeout: 5.0)
@ -873,6 +895,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
}, shareAccountContact: { [weak self] in }, shareAccountContact: { [weak self] in
if let strongSelf = self { if let strongSelf = self {
guard !strongSelf.presentationInterfaceState.isScheduledMessages else {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.ScheduledMessages_BotActionUnavailable, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
return
}
strongSelf.present(textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Conversation_ShareBotContactConfirmationTitle, text: strongSelf.presentationData.strings.Conversation_ShareBotContactConfirmation, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: { strongSelf.present(textAlertController(context: strongSelf.context, title: strongSelf.presentationData.strings.Conversation_ShareBotContactConfirmationTitle, text: strongSelf.presentationData.strings.Conversation_ShareBotContactConfirmation, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {
if let strongSelf = self { if let strongSelf = self {
let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.context.account.peerId) let _ = (strongSelf.context.account.postbox.loadedPeerWithId(strongSelf.context.account.peerId)
@ -1134,7 +1160,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
if let strongSelf = self { if let strongSelf = self {
strongSelf.openPeer(peerId: peerId, navigation: .chat(textInputState: nil, messageId: nil), fromMessage: nil) strongSelf.openPeer(peerId: peerId, navigation: .chat(textInputState: nil, subject: nil), fromMessage: nil)
} }
})) }))
if !mention.isEmpty { if !mention.isEmpty {
@ -1458,7 +1484,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
}, sendScheduledMessagesNow: { [weak self] messageIds in }, sendScheduledMessagesNow: { [weak self] messageIds in
if let strongSelf = self { if let strongSelf = self {
strongSelf.sendScheduledMessagesNow(messageIds) let _ = sendScheduledMessageNowInteractively(postbox: strongSelf.context.account.postbox, messageId: messageIds.first!).start()
} }
}, editScheduledMessagesTime: { [weak self] messageIds in }, editScheduledMessagesTime: { [weak self] messageIds in
if let strongSelf = self, let messageId = messageIds.first { if let strongSelf = self, let messageId = messageIds.first {
@ -2183,7 +2209,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var slowmodeState: ChatSlowmodeState? var slowmodeState: ChatSlowmodeState?
if let cachedData = combinedInitialData.cachedData as? CachedChannelData { if let cachedData = combinedInitialData.cachedData as? CachedChannelData {
pinnedMessageId = cachedData.pinnedMessageId pinnedMessageId = cachedData.pinnedMessageId
if let channel = combinedInitialData.initialData?.peer as? TelegramChannel, channel.isRestrictedBySlowmode, let timeout = cachedData.slowModeTimeout { if let channel = combinedInitialData.initialData?.peer as? TelegramChannel, channel.isRestrictedBySlowmode, let timeout = cachedData.slowModeTimeout, !strongSelf.presentationInterfaceState.isScheduledMessages {
if let slowmodeUntilTimestamp = calculateSlowmodeActiveUntilTimestamp(account: strongSelf.context.account, untilTimestamp: cachedData.slowModeValidUntilTimestamp) { if let slowmodeUntilTimestamp = calculateSlowmodeActiveUntilTimestamp(account: strongSelf.context.account, untilTimestamp: cachedData.slowModeValidUntilTimestamp) {
slowmodeState = ChatSlowmodeState(timeout: timeout, variant: .timestamp(slowmodeUntilTimestamp)) slowmodeState = ChatSlowmodeState(timeout: timeout, variant: .timestamp(slowmodeUntilTimestamp))
} }
@ -2480,6 +2506,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let strongSelf = self, let validLayout = strongSelf.validLayout { if let strongSelf = self, let validLayout = strongSelf.validLayout {
var mappedTransition: (ChatHistoryListViewTransition, ListViewUpdateSizeAndInsets?)? var mappedTransition: (ChatHistoryListViewTransition, ListViewUpdateSizeAndInsets?)?
let isScheduledMessages = strongSelf.presentationInterfaceState.isScheduledMessages
strongSelf.chatDisplayNode.containerLayoutUpdated(validLayout, navigationBarHeight: strongSelf.navigationHeight, transition: .animated(duration: 0.2, curve: .easeInOut), listViewTransaction: { updateSizeAndInsets, _, _ in strongSelf.chatDisplayNode.containerLayoutUpdated(validLayout, navigationBarHeight: strongSelf.navigationHeight, transition: .animated(duration: 0.2, curve: .easeInOut), listViewTransaction: { updateSizeAndInsets, _, _ in
var options = transition.options var options = transition.options
let _ = options.insert(.Synchronous) let _ = options.insert(.Synchronous)
@ -2493,17 +2520,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}) })
var maxInsertedItem: Int? var maxInsertedItem: Int?
var insertedIndex: Int?
var insertItems: [ListViewInsertItem] = [] var insertItems: [ListViewInsertItem] = []
for i in 0 ..< transition.insertItems.count { for i in 0 ..< transition.insertItems.count {
let item = transition.insertItems[i] let item = transition.insertItems[i]
if item.directionHint == .Down && (maxInsertedItem == nil || maxInsertedItem! < item.index) { if item.directionHint == .Down && (maxInsertedItem == nil || maxInsertedItem! < item.index) {
maxInsertedItem = item.index maxInsertedItem = item.index
} }
insertedIndex = item.index
insertItems.append(ListViewInsertItem(index: item.index, previousIndex: item.previousIndex, item: item.item, directionHint: item.directionHint == .Down ? .Up : nil)) insertItems.append(ListViewInsertItem(index: item.index, previousIndex: item.previousIndex, item: item.item, directionHint: item.directionHint == .Down ? .Up : nil))
} }
var scrollToItem: ListViewScrollToItem? var scrollToItem: ListViewScrollToItem?
if transition.historyView.originalView.laterId == nil { if isScheduledMessages, let insertedIndex = insertedIndex {
scrollToItem = ListViewScrollToItem(index: insertedIndex, position: .visible, animated: true, curve: .Default(duration: 0.2), directionHint: .Down)
} else if transition.historyView.originalView.laterId == nil {
scrollToItem = ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: 0.2), directionHint: .Up) scrollToItem = ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: 0.2), directionHint: .Up)
} }
@ -2559,9 +2590,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: transformedMessages) let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: transformedMessages)
|> deliverOnMainQueue).start(next: { _ in |> deliverOnMainQueue).start(next: { messageIds in
if let strongSelf = self { if let strongSelf = self {
strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory() if strongSelf.presentationInterfaceState.isScheduledMessages {
} else {
strongSelf.chatDisplayNode.historyNode.scrollToEndOfHistory()
}
} }
}) })
@ -3078,7 +3112,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
if let navigationController = strongSelf.navigationController as? NavigationController { if let navigationController = strongSelf.navigationController as? NavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), messageId: nil, keepStack: .always)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: nil, keepStack: .always))
} }
}, openPeerInfo: { [weak self] in }, openPeerInfo: { [weak self] in
self?.navigationButtonAction(.openChatInfo) self?.navigationButtonAction(.openChatInfo)
@ -3132,7 +3166,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
}, botSwitchChatWithPayload: { [weak self] peerId, payload in }, botSwitchChatWithPayload: { [weak self] peerId, payload in
if let strongSelf = self, case let .peer(currentPeerId) = strongSelf.chatLocation { if let strongSelf = self, case let .peer(currentPeerId) = strongSelf.chatLocation {
strongSelf.openPeer(peerId: peerId, navigation: .withBotStartPayload(ChatControllerInitialBotStart(payload: payload, behavior: .automatic(returnToPeerId: currentPeerId))), fromMessage: nil) strongSelf.openPeer(peerId: peerId, navigation: .withBotStartPayload(ChatControllerInitialBotStart(payload: payload, behavior: .automatic(returnToPeerId: currentPeerId, scheduled: strongSelf.presentationInterfaceState.isScheduledMessages))), fromMessage: nil)
} }
}, beginMediaRecording: { [weak self] isVideo in }, beginMediaRecording: { [weak self] isVideo in
guard let strongSelf = self else { guard let strongSelf = self else {
@ -3921,7 +3955,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let actions: [TextAlertAction] let actions: [TextAlertAction]
if moreInfo { if moreInfo {
actions = [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Generic_ErrorMoreInfo, action: { actions = [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Generic_ErrorMoreInfo, action: {
self?.openPeerMention("spambot", navigation: .chat(textInputState: nil, messageId: nil)) self?.openPeerMention("spambot", navigation: .chat(textInputState: nil, subject: nil))
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_OK, action: {})] }), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]
} else { } else {
actions = [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})] actions = [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]
@ -4634,7 +4668,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let account = self.context.account let account = self.context.account
let beginClear: (InteractiveMessagesDeletionType) -> Void = { [weak self] type in let beginClear: (InteractiveHistoryClearingType) -> Void = { [weak self] type in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@ -4642,7 +4676,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.historyNode.historyAppearsCleared = true strongSelf.chatDisplayNode.historyNode.historyAppearsCleared = true
let statusText: String let statusText: String
if case .forEveryone = type { if strongSelf.presentationInterfaceState.isScheduledMessages {
statusText = strongSelf.presentationData.strings.Undo_ScheduledMessagesCleared
} else if case .forEveryone = type {
statusText = strongSelf.presentationData.strings.Undo_ChatClearedForBothSides statusText = strongSelf.presentationData.strings.Undo_ChatClearedForBothSides
} else { } else {
statusText = strongSelf.presentationData.strings.Undo_ChatCleared statusText = strongSelf.presentationData.strings.Undo_ChatCleared
@ -4661,16 +4697,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme) let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme)
var items: [ActionSheetItem] = [] var items: [ActionSheetItem] = []
if canRemoveGlobally { if self.presentationInterfaceState.isScheduledMessages {
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ScheduledMessages_ClearAllConfirmation, color: .destructive, action: { [weak actionSheet] in
actionSheet?.dismissAnimated()
beginClear(.scheduledMessages)
}))
} else if canRemoveGlobally {
items.append(DeleteChatPeerActionSheetItem(context: self.context, peer: mainPeer, chatPeer: chatPeer, action: .clearHistory, strings: self.presentationData.strings)) items.append(DeleteChatPeerActionSheetItem(context: self.context, peer: mainPeer, chatPeer: chatPeer, action: .clearHistory, strings: self.presentationData.strings))
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).0, color: .destructive, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).0, color: .destructive, action: { [weak actionSheet] in
beginClear(.forEveryone) beginClear(.forEveryone)
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
})) }))
items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForCurrentUser, color: .destructive, action: { [weak actionSheet] in items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForCurrentUser, color: .destructive, action: { [weak actionSheet] in
beginClear(.forLocalPeer)
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
beginClear(.forLocalPeer)
})) }))
} else { } else {
items.append(ActionSheetTextItem(title: text)) items.append(ActionSheetTextItem(title: text))
@ -4876,13 +4917,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.Chat_AttachmentMultipleFilesDisabled, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.Chat_AttachmentMultipleFilesDisabled, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}, sendMessagesWithSignals: { [weak self] signals, silentPosting in }, sendMessagesWithSignals: { [weak self] signals, mode in
if !inputText.string.isEmpty { if !inputText.string.isEmpty {
//strongSelf.clearInputText() //strongSelf.clearInputText()
} }
if editMediaOptions != nil { if editMediaOptions != nil {
self?.editMessageMediaWithLegacySignals(signals!) self?.editMessageMediaWithLegacySignals(signals!)
} else { } else {
var silentPosting = false
//if mode ==
self?.enqueueMediaMessages(signals: signals, silentPosting: silentPosting) self?.enqueueMediaMessages(signals: signals, silentPosting: silentPosting)
} }
}, selectRecentlyUsedInlineBot: { [weak self] peer in }, selectRecentlyUsedInlineBot: { [weak self] peer in
@ -5043,9 +5086,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.Chat_AttachmentLimitReached, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.Chat_AttachmentLimitReached, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root))
}) })
controller.descriptionGenerator = legacyAssetPickerItemGenerator() controller.descriptionGenerator = legacyAssetPickerItemGenerator()
controller.completionBlock = { [weak legacyController] signals, silentPosting in controller.completionBlock = { [weak legacyController] signals, mode in
if let legacyController = legacyController { if let legacyController = legacyController {
legacyController.dismiss() legacyController.dismiss()
var silentPosting = false
completion(signals!, silentPosting) completion(signals!, silentPosting)
} }
} }
@ -5149,7 +5193,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}) })
strongSelf.sendMessages([message]) strongSelf.sendMessages([message])
} }
}, theme: strongSelf.presentationData.theme), in: .window(.root)) }, theme: strongSelf.presentationData.theme, hasLiveLocation: !strongSelf.presentationInterfaceState.isScheduledMessages), in: .window(.root))
}) })
} }
@ -5292,10 +5336,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
private func sendScheduledMessagesNow(_ messageId: [MessageId]) {
let _ = sendScheduledMessageNowInteractively(postbox: self.context.account.postbox, messageId: messageId.first!).start()
}
private func sendMessages(_ messages: [EnqueueMessage], commit: Bool = false) { private func sendMessages(_ messages: [EnqueueMessage], commit: Bool = false) {
guard case let .peer(peerId) = self.chatLocation else { guard case let .peer(peerId) = self.chatLocation else {
return return
@ -5327,12 +5367,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
private func enqueueMediaMessages(signals: [Any]?, silentPosting: Bool) { private func enqueueMediaMessages(signals: [Any]?, silentPosting: Bool, scheduleTime: Int32? = nil) {
if case .peer = self.chatLocation { if case .peer = self.chatLocation {
self.enqueueMediaMessageDisposable.set((legacyAssetPickerEnqueueMessages(account: self.context.account, signals: signals!) self.enqueueMediaMessageDisposable.set((legacyAssetPickerEnqueueMessages(account: self.context.account, signals: signals!)
|> deliverOnMainQueue).start(next: { [weak self] messages in |> deliverOnMainQueue).start(next: { [weak self] messages in
if let strongSelf = self { if let strongSelf = self {
let messages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting) let messages = strongSelf.transformEnqueueMessages(messages, silentPosting: silentPosting, scheduleTime: scheduleTime)
let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId let replyMessageId = strongSelf.presentationInterfaceState.interfaceState.replyMessageId
strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({
if let strongSelf = self { if let strongSelf = self {
@ -5838,9 +5878,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
if case let .peer(peerId) = self.chatLocation, let messageId = messageLocation.messageId, (messageId.peerId != peerId && !forceInCurrentChat) || (self.presentationInterfaceState.isScheduledMessages && messageId.id != 0) { if case let .peer(peerId) = self.chatLocation, let messageId = messageLocation.messageId, (messageId.peerId != peerId && !forceInCurrentChat) || (self.presentationInterfaceState.isScheduledMessages && messageId.id != 0 && !Namespaces.Message.allScheduled.contains(messageId.namespace)) {
if let navigationController = self.navigationController as? NavigationController { if let navigationController = self.navigationController as? NavigationController {
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), messageId: messageId, keepStack: .always)) self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageId.peerId), subject: .message(messageId), keepStack: .always))
} }
} else if case let .peer(peerId) = self.chatLocation, (messageLocation.peerId == peerId || forceInCurrentChat) { } else if case let .peer(peerId) = self.chatLocation, (messageLocation.peerId == peerId || forceInCurrentChat) {
if let fromIndex = fromIndex { if let fromIndex = fromIndex {
@ -5853,6 +5893,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.messageIndexDisposable.set(nil) self.messageIndexDisposable.set(nil)
self.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: message.index, animated: animated, scrollPosition: scrollPosition) self.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: message.index, animated: animated, scrollPosition: scrollPosition)
completion?() completion?()
} else if case let .index(index) = messageLocation, index.id.id == 0 && index.timestamp > 0, self.presentationInterfaceState.isScheduledMessages {
self.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: index, animated: animated, scrollPosition: scrollPosition)
} else { } else {
self.loadingMessage.set(true) self.loadingMessage.set(true)
let searchLocation: ChatHistoryInitialSearchLocation let searchLocation: ChatHistoryInitialSearchLocation
@ -6117,7 +6159,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
} }
})) }))
case let .chat(textInputState, messageId): case let .chat(textInputState, subject):
if let textInputState = textInputState { if let textInputState = textInputState {
let _ = (self.context.account.postbox.transaction({ transaction -> Void in let _ = (self.context.account.postbox.transaction({ transaction -> Void in
transaction.updatePeerChatInterfaceState(peerId, update: { currentState in transaction.updatePeerChatInterfaceState(peerId, update: { currentState in
@ -6130,11 +6172,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}) })
|> deliverOnMainQueue).start(completed: { [weak self] in |> deliverOnMainQueue).start(completed: { [weak self] 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(peerId), messageId: messageId, updateTextInputState: textInputState)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: subject, updateTextInputState: textInputState))
} }
}) })
} else { } else {
(self.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId), subject: messageId.flatMap({ .message($0) }))) (self.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId), subject: subject))
} }
case let .withBotStartPayload(botStart): case let .withBotStartPayload(botStart):
(self.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId), botStart: botStart)) (self.navigationController as? NavigationController)?.pushViewController(ChatControllerImpl(context: self.context, chatLocation: .peer(peerId), botStart: botStart))
@ -6253,7 +6295,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var navigation = navigation var navigation = navigation
if case .default = navigation { if case .default = navigation {
if let peer = peer as? TelegramUser, peer.botInfo != nil { if let peer = peer as? TelegramUser, peer.botInfo != nil {
navigation = .chat(textInputState: nil, messageId: nil) navigation = .chat(textInputState: nil, subject: nil)
} }
} }
strongSelf.openResolved(.peer(peer.id, navigation)) strongSelf.openResolved(.peer(peer.id, navigation))
@ -6504,13 +6546,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return return
} }
switch navigation { switch navigation {
case let .chat(_, messageId): case let .chat(_, subject):
if case .peer(peerId) = strongSelf.chatLocation { if case .peer(peerId) = strongSelf.chatLocation {
if let messageId = messageId { if let subject = subject, case let .message(messageId) = subject {
strongSelf.navigateToMessage(from: nil, to: .id(messageId)) strongSelf.navigateToMessage(from: nil, to: .id(messageId))
} }
} else if let navigationController = strongSelf.navigationController as? NavigationController { } else if let navigationController = strongSelf.navigationController as? NavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), messageId: messageId, keepStack: .always)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: subject, keepStack: .always))
} }
case .info: case .info:
strongSelf.navigationActionDisposable.set((strongSelf.context.account.postbox.loadedPeerWithId(peerId) strongSelf.navigationActionDisposable.set((strongSelf.context.account.postbox.loadedPeerWithId(peerId)

View File

@ -455,8 +455,8 @@ final class ChatEmptyNode: ASDisplayNode {
} }
let contentType: ChatEmptyNodeContentType let contentType: ChatEmptyNodeContentType
if let peer = interfaceState.renderedPeer?.peer { if let peer = interfaceState.renderedPeer?.peer, !interfaceState.isScheduledMessages {
if peer.id == self.accountPeerId && !interfaceState.isScheduledMessages { if peer.id == self.accountPeerId {
contentType = .cloud contentType = .cloud
} else if let _ = peer as? TelegramSecretChat { } else if let _ = peer as? TelegramSecretChat {
contentType = .secret contentType = .secret

View File

@ -1113,10 +1113,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Scroll(index: .message(toIndex), anchorIndex: .message(toIndex), sourceIndex: .message(fromIndex), scrollPosition: scrollPosition, animated: animated), id: self.takeNextHistoryLocationId()) self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Scroll(index: .message(toIndex), anchorIndex: .message(toIndex), sourceIndex: .message(fromIndex), scrollPosition: scrollPosition, animated: animated), id: self.takeNextHistoryLocationId())
} }
func scrollWithDeltaOffset(_ offset: CGFloat) {
}
public func anchorMessageInCurrentHistoryView() -> Message? { public func anchorMessageInCurrentHistoryView() -> Message? {
if let historyView = self.historyView { if let historyView = self.historyView {
if let visibleRange = self.displayedItemRange.visibleRange { if let visibleRange = self.displayedItemRange.visibleRange {

View File

@ -26,36 +26,36 @@ func preloadedChatHistoryViewForLocation(_ location: ChatHistoryLocationInput, a
} }
func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: Account, chatLocation: ChatLocation, scheduled: Bool, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags?, additionalData: [AdditionalMessageHistoryViewData], orderStatistics: MessageHistoryViewOrderStatistics = []) -> Signal<ChatHistoryViewUpdate, NoError> { func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: Account, chatLocation: ChatLocation, scheduled: Bool, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags?, additionalData: [AdditionalMessageHistoryViewData], orderStatistics: MessageHistoryViewOrderStatistics = []) -> Signal<ChatHistoryViewUpdate, NoError> {
if scheduled { if scheduled {
var preloaded = false var first = true
var fadeIn = false var chatScrollPosition: ChatHistoryViewScrollPosition?
if case let .Scroll(index, _, sourceIndex, position, animated) = location.content {
let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up
chatScrollPosition = .index(index: index, position: position, directionHint: directionHint, animated: animated)
}
return account.viewTracker.scheduledMessagesViewForLocation(chatLocation) return account.viewTracker.scheduledMessagesViewForLocation(chatLocation)
|> map { view, updateType, initialData -> ChatHistoryViewUpdate in |> map { view, updateType, initialData -> ChatHistoryViewUpdate in
let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation)
let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData) let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData)
if preloaded { if view.isLoading {
return .HistoryView(view: view, type: .Generic(type: updateType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: combinedInitialData, id: location.id) return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType))
} else {
if view.isLoading {
return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType))
}
var scrollPosition: ChatHistoryViewScrollPosition?
// if let historyScrollState = (initialData?.chatInterfaceState as? ChatInterfaceState)?.historyScrollState, tagMask == nil {
// scrollPosition = .positionRestoration(index: historyScrollState.messageIndex, relativeOffset: CGFloat(historyScrollState.relativeOffset))
// } else {
// if view.entries.isEmpty && (view.holeEarlier || view.holeLater) {
// fadeIn = true
// return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType))
// }
// }
preloaded = true
return .HistoryView(view: view, type: .Initial(fadeIn: fadeIn), scrollPosition: scrollPosition, flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id)
} }
let type: ChatHistoryViewUpdateType
let scrollPosition: ChatHistoryViewScrollPosition? = first ? chatScrollPosition : nil
if first {
first = false
if chatScrollPosition == nil {
type = .Initial(fadeIn: false)
} else {
type = .Generic(type: .UpdateVisible)
}
} else {
type = .Generic(type: updateType)
}
return .HistoryView(view: view, type: type, scrollPosition: scrollPosition, flashIndicators: false, originalScrollPosition: chatScrollPosition, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id)
} }
} else { } else {
switch location.content { switch location.content {

View File

@ -379,8 +379,12 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
avatarInset = 0.0 avatarInset = 0.0
} }
let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp())
var needShareButton = false var needShareButton = false
if item.message.id.peerId == item.context.account.peerId { if isFailed {
needShareButton = false
} else if item.message.id.peerId == item.context.account.peerId {
for attribute in item.content.firstMessage.attributes { for attribute in item.content.firstMessage.attributes {
if let _ = attribute as? SourceReferenceMessageAttribute { if let _ = attribute as? SourceReferenceMessageAttribute {
needShareButton = true needShareButton = true
@ -424,7 +428,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
} }
var deliveryFailedInset: CGFloat = 0.0 var deliveryFailedInset: CGFloat = 0.0
if item.content.firstMessage.flags.contains(.Failed) { if isFailed {
deliveryFailedInset += 24.0 deliveryFailedInset += 24.0
} }
@ -446,7 +450,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
if item.message.effectivelyIncoming(item.context.account.peerId) { if item.message.effectivelyIncoming(item.context.account.peerId) {
statusType = .FreeIncoming statusType = .FreeIncoming
} else { } else {
if item.message.flags.contains(.Failed) { if isFailed {
statusType = .FreeOutgoing(.Failed) statusType = .FreeOutgoing(.Failed)
} else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged {
statusType = .FreeOutgoing(.Sending) statusType = .FreeOutgoing(.Sending)
@ -659,7 +663,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
strongSelf.replyInfoNode = nil strongSelf.replyInfoNode = nil
} }
if item.content.firstMessage.flags.contains(.Failed) { if isFailed {
let deliveryFailedNode: ChatMessageDeliveryFailedNode let deliveryFailedNode: ChatMessageDeliveryFailedNode
var isAppearing = false var isAppearing = false
if let current = strongSelf.deliveryFailedNode { if let current = strongSelf.deliveryFailedNode {
@ -740,7 +744,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
var navigate: ChatControllerInteractionNavigateToPeer var navigate: ChatControllerInteractionNavigateToPeer
if item.content.firstMessage.id.peerId == item.context.account.peerId { if item.content.firstMessage.id.peerId == item.context.account.peerId {
navigate = .chat(textInputState: nil, messageId: nil) navigate = .chat(textInputState: nil, subject: nil)
} else { } else {
navigate = .info navigate = .info
} }
@ -748,7 +752,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, messageId: attribute.messageId) navigate = .chat(textInputState: nil, subject: .message(attribute.messageId))
} }
} }

View File

@ -666,8 +666,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
avatarInset = 0.0 avatarInset = 0.0
} }
let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp())
var needShareButton = false var needShareButton = false
if item.message.flags.contains(.Failed) { if isFailed {
needShareButton = false needShareButton = false
} else if item.message.id.peerId == item.context.account.peerId { } else if item.message.id.peerId == item.context.account.peerId {
if let _ = sourceReference { if let _ = sourceReference {
@ -731,7 +733,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
} }
var deliveryFailedInset: CGFloat = 0.0 var deliveryFailedInset: CGFloat = 0.0
if item.content.firstMessage.flags.contains(.Failed) { if isFailed {
deliveryFailedInset += 24.0 deliveryFailedInset += 24.0
} }
@ -1032,7 +1034,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
if message.effectivelyIncoming(item.context.account.peerId) { if message.effectivelyIncoming(item.context.account.peerId) {
statusType = .ImageIncoming statusType = .ImageIncoming
} else { } else {
if message.flags.contains(.Failed) { if isFailed {
statusType = .ImageOutgoing(.Failed) statusType = .ImageOutgoing(.Failed)
} else if message.flags.isSending && !message.isSentOrAcknowledged { } else if message.flags.isSending && !message.isSentOrAcknowledged {
statusType = .ImageOutgoing(.Sending) statusType = .ImageOutgoing(.Sending)
@ -1587,7 +1589,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
strongSelf.backgroundType = backgroundType strongSelf.backgroundType = backgroundType
if item.content.firstMessage.flags.contains(.Failed) { let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp())
if isFailed {
let deliveryFailedNode: ChatMessageDeliveryFailedNode let deliveryFailedNode: ChatMessageDeliveryFailedNode
var isAppearing = false var isAppearing = false
if let current = strongSelf.deliveryFailedNode { if let current = strongSelf.deliveryFailedNode {
@ -2133,7 +2136,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
var navigate: ChatControllerInteractionNavigateToPeer var navigate: ChatControllerInteractionNavigateToPeer
if item.content.firstMessage.id.peerId == item.context.account.peerId { if item.content.firstMessage.id.peerId == item.context.account.peerId {
navigate = .chat(textInputState: nil, messageId: nil) navigate = .chat(textInputState: nil, subject: nil)
} else { } else {
navigate = .info navigate = .info
} }
@ -2141,7 +2144,7 @@ class ChatMessageBubbleItemNode: 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, messageId: attribute.messageId) navigate = .chat(textInputState: nil, subject: .message(attribute.messageId))
} }
} }
@ -2225,7 +2228,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView {
break loop break loop
case let .peerMention(peerId, _): case let .peerMention(peerId, _):
foundTapAction = true foundTapAction = true
self.item?.controllerInteraction.openPeer(peerId, .chat(textInputState: nil, messageId: nil), nil) self.item?.controllerInteraction.openPeer(peerId, .chat(textInputState: nil, subject: nil), nil)
break loop break loop
case let .textMention(name): case let .textMention(name):
foundTapAction = true foundTapAction = true

View File

@ -580,7 +580,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
var navigate: ChatControllerInteractionNavigateToPeer var navigate: ChatControllerInteractionNavigateToPeer
if item.content.firstMessage.id.peerId == item.context.account.peerId { if item.content.firstMessage.id.peerId == item.context.account.peerId {
navigate = .chat(textInputState: nil, messageId: nil) navigate = .chat(textInputState: nil, subject: nil)
} else { } else {
navigate = .info navigate = .info
} }
@ -588,7 +588,7 @@ class ChatMessageInstantVideoItemNode: 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, messageId: attribute.messageId) navigate = .chat(textInputState: nil, subject: .message(attribute.messageId))
} }
} }
@ -631,7 +631,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView {
} }
item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId) item.controllerInteraction.navigateToMessage(item.message.id, sourceMessageId)
} else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id { } else if let id = forwardInfo.source?.id ?? forwardInfo.author?.id {
item.controllerInteraction.openPeer(id, .chat(textInputState: nil, messageId: nil), nil) item.controllerInteraction.openPeer(id, .chat(textInputState: nil, subject: nil), nil)
} else if let _ = forwardInfo.authorSignature { } else if let _ = forwardInfo.authorSignature {
item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, forwardInfoNode, nil) item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, forwardInfoNode, nil)
} }

View File

@ -181,8 +181,10 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
avatarInset = 0.0 avatarInset = 0.0
} }
let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp())
var needShareButton = false var needShareButton = false
if item.message.flags.contains(.Failed) { if isFailed {
needShareButton = false needShareButton = false
} else if item.message.id.peerId == item.context.account.peerId { } else if item.message.id.peerId == item.context.account.peerId {
for attribute in item.content.firstMessage.attributes { for attribute in item.content.firstMessage.attributes {
@ -228,7 +230,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
} }
var deliveryFailedInset: CGFloat = 0.0 var deliveryFailedInset: CGFloat = 0.0
if item.content.firstMessage.flags.contains(.Failed) { if isFailed {
deliveryFailedInset += 24.0 deliveryFailedInset += 24.0
} }
@ -246,7 +248,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
if item.message.effectivelyIncoming(item.context.account.peerId) { if item.message.effectivelyIncoming(item.context.account.peerId) {
statusType = .FreeIncoming statusType = .FreeIncoming
} else { } else {
if item.message.flags.contains(.Failed) { if isFailed {
statusType = .FreeOutgoing(.Failed) statusType = .FreeOutgoing(.Failed)
} else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged {
statusType = .FreeOutgoing(.Sending) statusType = .FreeOutgoing(.Sending)
@ -503,7 +505,8 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
strongSelf.replyInfoNode = nil strongSelf.replyInfoNode = nil
} }
if item.content.firstMessage.flags.contains(.Failed) {
if isFailed {
let deliveryFailedNode: ChatMessageDeliveryFailedNode let deliveryFailedNode: ChatMessageDeliveryFailedNode
var isAppearing = false var isAppearing = false
if let current = strongSelf.deliveryFailedNode { if let current = strongSelf.deliveryFailedNode {
@ -584,7 +587,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
var navigate: ChatControllerInteractionNavigateToPeer var navigate: ChatControllerInteractionNavigateToPeer
if item.content.firstMessage.id.peerId == item.context.account.peerId { if item.content.firstMessage.id.peerId == item.context.account.peerId {
navigate = .chat(textInputState: nil, messageId: nil) navigate = .chat(textInputState: nil, subject: nil)
} else { } else {
navigate = .info navigate = .info
} }
@ -592,7 +595,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, messageId: attribute.messageId) navigate = .chat(textInputState: nil, subject: .message(attribute.messageId))
} }
} }

View File

@ -48,6 +48,8 @@ public final class ChatPresentationData {
let nameDisplayOrder: PresentationPersonNameOrder let nameDisplayOrder: PresentationPersonNameOrder
let disableAnimations: Bool let disableAnimations: Bool
let largeEmoji: Bool let largeEmoji: Bool
let animatedEmojiScale: CGFloat
let isPreview: Bool
let messageFont: UIFont let messageFont: UIFont
let messageEmojiFont1: UIFont let messageEmojiFont1: UIFont
@ -59,9 +61,7 @@ public final class ChatPresentationData {
let messageFixedFont: UIFont let messageFixedFont: UIFont
let messageBlockQuoteFont: UIFont let messageBlockQuoteFont: UIFont
let animatedEmojiScale: CGFloat init(theme: ChatPresentationThemeData, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool, animatedEmojiScale: CGFloat = 1.0, isPreview: Bool = false) {
init(theme: ChatPresentationThemeData, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool, animatedEmojiScale: CGFloat = 1.0) {
self.theme = theme self.theme = theme
self.fontSize = fontSize self.fontSize = fontSize
self.strings = strings self.strings = strings
@ -69,6 +69,7 @@ public final class ChatPresentationData {
self.nameDisplayOrder = nameDisplayOrder self.nameDisplayOrder = nameDisplayOrder
self.disableAnimations = disableAnimations self.disableAnimations = disableAnimations
self.largeEmoji = largeEmoji self.largeEmoji = largeEmoji
self.isPreview = isPreview
let baseFontSize = fontSize.baseDisplaySize let baseFontSize = fontSize.baseDisplaySize
self.messageFont = UIFont.systemFont(ofSize: baseFontSize) self.messageFont = UIFont.systemFont(ofSize: baseFontSize)

View File

@ -785,12 +785,11 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
strongSelf.controllerInteraction.presentController(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_ErrorInaccessibleMessage, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil) strongSelf.controllerInteraction.presentController(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.Conversation_ErrorInaccessibleMessage, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
case .botStart: case .botStart:
break break
//strongSelf.openPeer(peerId: peerId, navigation: .withBotStartPayload(ChatControllerInitialBotStart(payload: payload, behavior: .interactive)), fromMessage: nil)
case .groupBotStart: case .groupBotStart:
break break
case let .channelMessage(peerId, messageId): case let .channelMessage(peerId, messageId):
if let navigationController = strongSelf.getNavigationController() { if let navigationController = strongSelf.getNavigationController() {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), messageId: messageId)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: .message(messageId)))
} }
case let .stickerPack(name): case let .stickerPack(name):
strongSelf.presentController(StickerPackPreviewController(context: strongSelf.context, stickerPack: .name(name), parentNavigationController: strongSelf.getNavigationController()), nil) strongSelf.presentController(StickerPackPreviewController(context: strongSelf.context, stickerPack: .name(name), parentNavigationController: strongSelf.getNavigationController()), nil)

View File

@ -118,6 +118,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
strongSelf.updateMinimumDate() strongSelf.updateMinimumDate()
strongSelf.pickerView.layer.addShakeAnimation() strongSelf.pickerView.layer.addShakeAnimation()
} else { } else {
strongSelf.doneButton.isUserInteractionEnabled = false
strongSelf.completion?(Int32(strongSelf.pickerView.date.timeIntervalSince1970)) strongSelf.completion?(Int32(strongSelf.pickerView.date.timeIntervalSince1970))
} }
} }

View File

@ -23,7 +23,7 @@ private enum ChatSendMessageActionIcon {
case .schedule: case .schedule:
imageName = "Chat/Input/Menu/ScheduleIcon" imageName = "Chat/Input/Menu/ScheduleIcon"
} }
return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.actionSheet.primaryTextColor) return generateTintedImage(image: UIImage(bundleImageName: imageName), color: theme.contextMenu.primaryColor)
} }
} }
@ -33,6 +33,7 @@ private final class ActionSheetItemNode: ASDisplayNode {
private let action: () -> Void private let action: () -> Void
private let separatorNode: ASDisplayNode private let separatorNode: ASDisplayNode
private let backgroundNode: ASDisplayNode
private let highlightedBackgroundNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode
private let buttonNode: HighlightTrackingButtonNode private let buttonNode: HighlightTrackingButtonNode
private let iconNode: ASImageNode private let iconNode: ASImageNode
@ -46,21 +47,35 @@ private final class ActionSheetItemNode: ASDisplayNode {
self.action = action self.action = action
self.separatorNode = ASDisplayNode() self.separatorNode = ASDisplayNode()
self.separatorNode.backgroundColor = theme.actionSheet.opaqueItemSeparatorColor self.separatorNode.backgroundColor = theme.contextMenu.itemSeparatorColor
self.backgroundNode = ASDisplayNode()
self.backgroundNode.isAccessibilityElement = false
self.backgroundNode.backgroundColor = theme.contextMenu.itemBackgroundColor
self.highlightedBackgroundNode = ASDisplayNode() self.highlightedBackgroundNode = ASDisplayNode()
self.highlightedBackgroundNode.backgroundColor = theme.actionSheet.opaqueItemHighlightedBackgroundColor self.highlightedBackgroundNode.isAccessibilityElement = false
self.highlightedBackgroundNode.backgroundColor = theme.contextMenu.itemHighlightedBackgroundColor
self.highlightedBackgroundNode.alpha = 0.0 self.highlightedBackgroundNode.alpha = 0.0
self.buttonNode = HighlightTrackingButtonNode() self.buttonNode = HighlightTrackingButtonNode()
self.buttonNode.isAccessibilityElement = true
self.buttonNode.accessibilityLabel = title
self.titleNode = ImmediateTextNode() self.titleNode = ImmediateTextNode()
self.titleNode.isAccessibilityElement = false
self.titleNode.maximumNumberOfLines = 1 self.titleNode.maximumNumberOfLines = 1
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: theme.actionSheet.primaryTextColor) self.titleNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: theme.contextMenu.primaryColor)
self.titleNode.isUserInteractionEnabled = false
self.titleNode.displaysAsynchronously = false
self.iconNode = ASImageNode() self.iconNode = ASImageNode()
self.iconNode.image = icon.image(theme: theme) self.iconNode.image = icon.image(theme: theme)
self.iconNode.contentMode = .center self.iconNode.contentMode = .center
self.iconNode.isAccessibilityElement = false
self.iconNode.displaysAsynchronously = false
self.iconNode.displayWithoutProcessing = true
self.iconNode.isUserInteractionEnabled = false
super.init() super.init()
@ -87,9 +102,10 @@ private final class ActionSheetItemNode: ASDisplayNode {
} }
func updateTheme(_ theme: PresentationTheme) { func updateTheme(_ theme: PresentationTheme) {
self.separatorNode.backgroundColor = theme.actionSheet.opaqueItemSeparatorColor self.separatorNode.backgroundColor = theme.contextMenu.itemSeparatorColor
self.highlightedBackgroundNode.backgroundColor = theme.actionSheet.opaqueItemHighlightedBackgroundColor self.backgroundNode.backgroundColor = theme.contextMenu.itemBackgroundColor
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.regular(17.0), textColor: theme.actionSheet.primaryTextColor) self.highlightedBackgroundNode.backgroundColor = theme.contextMenu.itemHighlightedBackgroundColor
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.regular(17.0), textColor: theme.contextMenu.primaryColor)
self.iconNode.image = self.icon.image(theme: theme) self.iconNode.image = self.icon.image(theme: theme)
if let maxWidth = self.maxWidth { if let maxWidth = self.maxWidth {
@ -180,11 +196,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
self.dimNode = ASDisplayNode() self.dimNode = ASDisplayNode()
self.dimNode.alpha = 1.0 self.dimNode.alpha = 1.0
if self.presentationData.theme.chatList.searchBarKeyboardColor == .light { self.dimNode.backgroundColor = self.presentationData.theme.contextMenu.dimColor
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.04)
} else {
self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2)
}
self.sendButtonNode = HighlightableButtonNode() self.sendButtonNode = HighlightableButtonNode()
self.sendButtonNode.imageNode.displayWithoutProcessing = false self.sendButtonNode.imageNode.displayWithoutProcessing = false
@ -205,8 +217,8 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
self.scrollNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0) self.scrollNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0)
self.contentContainerNode = ASDisplayNode() self.contentContainerNode = ASDisplayNode()
self.contentContainerNode.backgroundColor = self.presentationData.theme.actionSheet.opaqueItemBackgroundColor self.contentContainerNode.backgroundColor = self.presentationData.theme.contextMenu.backgroundColor
self.contentContainerNode.cornerRadius = 12.0 self.contentContainerNode.cornerRadius = 14.0
self.contentContainerNode.clipsToBounds = true self.contentContainerNode.clipsToBounds = true
var contentNodes: [ActionSheetItemNode] = [] var contentNodes: [ActionSheetItemNode] = []
@ -296,19 +308,18 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
} }
self.presentationData = presentationData self.presentationData = presentationData
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark { if #available(iOS 9.0, *) {
self.effectView.effect = UIBlurEffect(style: .dark)
} else { } else {
self.effectView.effect = UIBlurEffect(style: .light) if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark {
self.effectView.effect = UIBlurEffect(style: .dark)
} else {
self.effectView.effect = UIBlurEffect(style: .light)
}
} }
if self.presentationData.theme.chatList.searchBarKeyboardColor == .light { self.dimNode.backgroundColor = presentationData.theme.contextMenu.dimColor
self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.04)
} else {
self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2)
}
self.contentContainerNode.backgroundColor = self.presentationData.theme.actionSheet.opaqueItemBackgroundColor self.contentContainerNode.backgroundColor = self.presentationData.theme.contextMenu.backgroundColor
self.textCoverNode.backgroundColor = self.presentationData.theme.chat.inputPanel.inputBackgroundColor self.textCoverNode.backgroundColor = self.presentationData.theme.chat.inputPanel.inputBackgroundColor
self.buttonCoverNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelBackgroundColor self.buttonCoverNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelBackgroundColor
self.sendButtonNode.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(self.presentationData.theme), for: []) self.sendButtonNode.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(self.presentationData.theme), for: [])
@ -329,39 +340,14 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
func animateIn() { func animateIn() {
self.textInputNode.textView.setContentOffset(self.textInputNode.textView.contentOffset, animated: false) self.textInputNode.textView.setContentOffset(self.textInputNode.textView.contentOffset, animated: false)
UIView.animate(withDuration: 0.4, animations: { UIView.animate(withDuration: 0.2, animations: {
if #available(iOS 9.0, *) { if #available(iOS 9.0, *) {
if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark { self.effectView.effect = makeCustomZoomBlurEffect()
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.effectView.effect = UIBlurEffect(style: .regular)
if self.effectView.subviews.count == 2 {
self.effectView.subviews[1].isHidden = true
}
} else {
self.effectView.effect = UIBlurEffect(style: .dark)
}
} else {
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
self.effectView.effect = UIBlurEffect(style: .regular)
} else {
self.effectView.effect = UIBlurEffect(style: .light)
}
}
} else { } else {
self.effectView.alpha = 1.0 self.effectView.alpha = 1.0
} }
}, completion: { [weak self] _ in }, completion: { _ in })
guard let strongSelf = self else { self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
return
}
if strongSelf.presentationData.theme.chatList.searchBarKeyboardColor == .dark {
if strongSelf.effectView.subviews.count == 2 {
strongSelf.effectView.subviews[1].isHidden = true
}
}
})
self.effectView.subviews[1].layer.removeAnimation(forKey: "backgroundColor")
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
self.contentContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.contentContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.messageBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) self.messageBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
@ -401,9 +387,11 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
let textOffset = self.textInputNode.textView.contentSize.height - self.textInputNode.textView.contentOffset.y - self.textInputNode.textView.frame.height let textOffset = self.textInputNode.textView.contentSize.height - self.textInputNode.textView.contentOffset.y - self.textInputNode.textView.frame.height
self.fromMessageTextNode.layer.animatePosition(from: CGPoint(x: 0.0, y: delta * 2.0 + textOffset), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true) self.fromMessageTextNode.layer.animatePosition(from: CGPoint(x: 0.0, y: delta * 2.0 + textOffset), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
self.toMessageTextNode.layer.animatePosition(from: CGPoint(x: 0.0, y: delta * 2.0 + textOffset), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true) self.toMessageTextNode.layer.animatePosition(from: CGPoint(x: 0.0, y: delta * 2.0 + textOffset), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
self.contentContainerNode.layer.animatePosition(from: CGPoint(x: 160.0, y: 0.0), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true) let springDuration: Double = 0.42
self.contentContainerNode.layer.animateScale(from: 0.45, to: 1.0, duration: duration, timingFunction: kCAMediaTimingFunctionSpring) let springDamping: CGFloat = 104.0
self.contentContainerNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, initialVelocity: 0.0, damping: springDamping)
self.contentContainerNode.layer.animateSpring(from: NSValue(cgPoint: CGPoint(x: 160.0, y: 0.0)), to: NSValue(cgPoint: CGPoint()), keyPath: "position", duration: springDuration, initialVelocity: 0.0, damping: springDamping, additive: true)
} }
} }
@ -436,7 +424,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
intermediateCompletion() intermediateCompletion()
}) })
self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false) self.dimNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false)
self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in }) self.contentContainerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in })
if cancel { if cancel {
@ -522,7 +510,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
let sideInset: CGFloat = 43.0 let sideInset: CGFloat = 43.0
var contentSize = CGSize() var contentSize = CGSize()
contentSize.width = min(layout.size.width - 40.0, 240.0) contentSize.width = min(layout.size.width - 40.0, 250.0)
var applyNodes: [(ASDisplayNode, CGFloat, (CGFloat) -> Void)] = [] var applyNodes: [(ASDisplayNode, CGFloat, (CGFloat) -> Void)] = []
for itemNode in self.contentNodes { for itemNode in self.contentNodes {
let (width, height, apply) = itemNode.updateLayout(maxWidth: layout.size.width - sideInset * 2.0) let (width, height, apply) = itemNode.updateLayout(maxWidth: layout.size.width - sideInset * 2.0)

View File

@ -57,7 +57,6 @@ private enum DebugControllerEntry: ItemListNodeEntry {
case resetData(PresentationTheme) case resetData(PresentationTheme)
case resetDatabase(PresentationTheme) case resetDatabase(PresentationTheme)
case resetHoles(PresentationTheme) case resetHoles(PresentationTheme)
case resetBiometricsData(PresentationTheme)
case optimizeDatabase(PresentationTheme) case optimizeDatabase(PresentationTheme)
case photoPreview(PresentationTheme, Bool) case photoPreview(PresentationTheme, Bool)
case knockoutWallpaper(PresentationTheme, Bool) case knockoutWallpaper(PresentationTheme, Bool)
@ -74,7 +73,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return DebugControllerSection.logging.rawValue return DebugControllerSection.logging.rawValue
case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries: case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries:
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .clearTips, .reimport, .resetData, .resetDatabase, .resetHoles, .resetBiometricsData, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .exportTheme: case .clearTips, .reimport, .resetData, .resetDatabase, .resetHoles, .optimizeDatabase, .photoPreview, .knockoutWallpaper, .exportTheme:
return DebugControllerSection.experiments.rawValue return DebugControllerSection.experiments.rawValue
case .versionInfo: case .versionInfo:
return DebugControllerSection.info.rawValue return DebugControllerSection.info.rawValue
@ -117,18 +116,16 @@ private enum DebugControllerEntry: ItemListNodeEntry {
return 15 return 15
case .resetHoles: case .resetHoles:
return 16 return 16
case .resetBiometricsData:
return 17
case .optimizeDatabase: case .optimizeDatabase:
return 18 return 17
case .photoPreview: case .photoPreview:
return 19 return 18
case .knockoutWallpaper: case .knockoutWallpaper:
return 21 return 19
case .exportTheme: case .exportTheme:
return 22 return 20
case .versionInfo: case .versionInfo:
return 23 return 21
} }
} }
@ -443,12 +440,6 @@ private enum DebugControllerEntry: ItemListNodeEntry {
controller.dismiss() controller.dismiss()
}) })
}) })
case let .resetBiometricsData(theme):
return ItemListActionItem(theme: theme, title: "Reset Biometrics Data", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
let _ = updatePresentationPasscodeSettingsInteractively(accountManager: arguments.sharedContext.accountManager, { settings in
return settings.withUpdatedBiometricsDomainState(nil).withUpdatedShareBiometricsDomainState(nil)
}).start()
})
case let .optimizeDatabase(theme): case let .optimizeDatabase(theme):
return ItemListActionItem(theme: theme, title: "Optimize Database", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { return ItemListActionItem(theme: theme, title: "Optimize Database", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
guard let context = arguments.context else { guard let context = arguments.context else {

View File

@ -63,8 +63,9 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAt
if peer is TelegramUser { if peer is TelegramUser {
controller.hasTimer = true controller.hasTimer = true
} }
controller.hasSilentPosting = true controller.hasSilentPosting = !isSecretChat
} }
controller.hasSchedule = !isSecretChat
let screenSize = parentController.view.bounds.size let screenSize = parentController.view.bounds.size
var startFrame = CGRect(x: 0, y: screenSize.height, width: screenSize.width, height: screenSize.height) var startFrame = CGRect(x: 0, y: screenSize.height, width: screenSize.width, height: screenSize.height)

View File

@ -13,11 +13,11 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
var found = false var found = false
var isFirst = true var isFirst = true
for controller in params.navigationController.viewControllers.reversed() { for controller in params.navigationController.viewControllers.reversed() {
if let controller = controller as? ChatControllerImpl, controller.chatLocation == params.chatLocation && controller.subject != .scheduledMessages { if let controller = controller as? ChatControllerImpl, controller.chatLocation == params.chatLocation && (controller.subject != .scheduledMessages || controller.subject == params.subject) {
if let updateTextInputState = params.updateTextInputState { if let updateTextInputState = params.updateTextInputState {
controller.updateTextInputState(updateTextInputState) controller.updateTextInputState(updateTextInputState)
} }
if let messageId = params.messageId { if let subject = params.subject, case let .message(messageId) = subject {
let navigationController = params.navigationController let navigationController = params.navigationController
let animated = params.animated let animated = params.animated
controller.navigateToMessage(messageLocation: .id(messageId), animated: isFirst, completion: { [weak navigationController, weak controller] in controller.navigateToMessage(messageLocation: .id(messageId), animated: isFirst, completion: { [weak navigationController, weak controller] in
@ -60,7 +60,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
} }
} }
} else { } else {
controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, subject: params.messageId.flatMap({ .message($0) }), botStart: params.botStart) controller = ChatControllerImpl(context: params.context, chatLocation: params.chatLocation, subject: params.subject, botStart: params.botStart)
} }
controller.purposefulAction = params.purposefulAction controller.purposefulAction = params.purposefulAction
let resolvedKeepStack: Bool let resolvedKeepStack: Bool

View File

@ -18,9 +18,9 @@ private func defaultNavigationForPeerId(_ peerId: PeerId?, navigation: ChatContr
if case .default = navigation { if case .default = navigation {
if let peerId = peerId { if let peerId = peerId {
if peerId.namespace == Namespaces.Peer.CloudUser { if peerId.namespace == Namespaces.Peer.CloudUser {
return .chat(textInputState: nil, messageId: nil) return .chat(textInputState: nil, subject: nil)
} else { } else {
return .chat(textInputState: nil, messageId: nil) return .chat(textInputState: nil, subject: nil)
} }
} else { } else {
return .info return .info
@ -81,7 +81,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
dismissInput() dismissInput()
present(controller, ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet)) present(controller, ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet))
case let .channelMessage(peerId, messageId): case let .channelMessage(peerId, messageId):
openPeer(peerId, .chat(textInputState: nil, messageId: messageId)) openPeer(peerId, .chat(textInputState: nil, subject: .message(messageId)))
case let .stickerPack(name): case let .stickerPack(name):
dismissInput() dismissInput()
let controller = StickerPackPreviewController(context: context, stickerPack: .name(name), parentNavigationController: navigationController) let controller = StickerPackPreviewController(context: context, stickerPack: .name(name), parentNavigationController: navigationController)
@ -92,7 +92,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
case let .join(link): case let .join(link):
dismissInput() dismissInput()
present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in
openPeer(peerId, .chat(textInputState: nil, messageId: nil)) openPeer(peerId, .chat(textInputState: nil, subject: nil))
}), nil) }), nil)
case let .localization(identifier): case let .localization(identifier):
dismissInput() dismissInput()

View File

@ -198,10 +198,10 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur
navigationController?.pushViewController(infoController) navigationController?.pushViewController(infoController)
} }
}) })
case let .chat(_, messageId): case let .chat(_, subject):
context.sharedContext.applicationBindings.dismissNativeController() context.sharedContext.applicationBindings.dismissNativeController()
if let navigationController = navigationController { if let navigationController = navigationController {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), messageId: messageId)) context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: subject))
} }
case let .withBotStartPayload(payload): case let .withBotStartPayload(payload):
context.sharedContext.applicationBindings.dismissNativeController() context.sharedContext.applicationBindings.dismissNativeController()

View File

@ -132,7 +132,7 @@ public class PeerMediaCollectionController: TelegramBaseController {
ActionSheetButtonItem(title: strongSelf.presentationData.strings.SharedMedia_ViewInChat, color: .accent, action: { [weak actionSheet] in ActionSheetButtonItem(title: strongSelf.presentationData.strings.SharedMedia_ViewInChat, color: .accent, action: { [weak actionSheet] in
actionSheet?.dismissAnimated() actionSheet?.dismissAnimated()
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(strongSelf.peerId), messageId: message.id)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(strongSelf.peerId), subject: .message(message.id)))
} }
}), }),
ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ContextMenuForward, color: .accent, action: { [weak actionSheet] in ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ContextMenuForward, color: .accent, action: { [weak actionSheet] in
@ -606,9 +606,9 @@ public class PeerMediaCollectionController: TelegramBaseController {
strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.navigationController as? NavigationController, openPeer: { peerId, navigation in strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.navigationController as? NavigationController, openPeer: { peerId, navigation in
if let strongSelf = self { if let strongSelf = self {
switch navigation { switch navigation {
case let .chat(_, messageId): case let .chat(_, subject):
if let navigationController = strongSelf.navigationController as? NavigationController { if let navigationController = strongSelf.navigationController as? NavigationController {
strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), messageId: messageId, keepStack: .always)) strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), subject: subject, keepStack: .always))
} }
case .info: case .info:
strongSelf.navigationActionDisposable.set((strongSelf.context.account.postbox.loadedPeerWithId(peerId) strongSelf.navigationActionDisposable.set((strongSelf.context.account.postbox.loadedPeerWithId(peerId)

View File

@ -487,7 +487,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist {
self.loadingItem = true self.loadingItem = true
self.updateState() self.updateState()
let namespaces: HistoryViewNamespaces let namespaces: MessageIdNamespaces
if Namespaces.Message.allScheduled.contains(anchor.id.namespace) { if Namespaces.Message.allScheduled.contains(anchor.id.namespace) {
namespaces = .just(Namespaces.Message.allScheduled) namespaces = .just(Namespaces.Message.allScheduled)
} else { } else {

View File

@ -22,9 +22,9 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
let openResolvedPeerImpl: (PeerId?, ChatControllerInteractionNavigateToPeer) -> Void = { [weak controller] peerId, navigation in let openResolvedPeerImpl: (PeerId?, ChatControllerInteractionNavigateToPeer) -> Void = { [weak controller] peerId, navigation in
context.sharedContext.openResolvedUrl(.peer(peerId, navigation), context: context, urlContext: .generic, navigationController: (controller?.navigationController as? NavigationController), openPeer: { (peerId, navigation) in context.sharedContext.openResolvedUrl(.peer(peerId, navigation), context: context, urlContext: .generic, navigationController: (controller?.navigationController as? NavigationController), openPeer: { (peerId, navigation) in
switch navigation { switch navigation {
case let .chat(_, messageId): case let .chat(_, subject):
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), messageId: messageId, keepStack: .always)) context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: subject, keepStack: .always))
} }
case .info: case .info:
let peerSignal: Signal<Peer?, NoError> let peerSignal: Signal<Peer?, NoError>
@ -54,7 +54,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
openResolvedPeerImpl(peerId, .default) openResolvedPeerImpl(peerId, .default)
case let .channelMessage(peerId, messageId): case let .channelMessage(peerId, messageId):
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), messageId: messageId)) context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peerId), subject: .message(messageId)))
} }
case let .stickerPack(name): case let .stickerPack(name):
controller.present(StickerPackPreviewController(context: context, stickerPack: .name(name), parentNavigationController: controller.navigationController as? NavigationController), in: .window(.root)) controller.present(StickerPackPreviewController(context: context, stickerPack: .name(name), parentNavigationController: controller.navigationController as? NavigationController), in: .window(.root))
@ -62,7 +62,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate
(controller.navigationController as? NavigationController)?.pushViewController(InstantPageController(context: context, webPage: webpage, sourcePeerType: .group, anchor: anchor)) (controller.navigationController as? NavigationController)?.pushViewController(InstantPageController(context: context, webPage: webpage, sourcePeerType: .group, anchor: anchor))
case let .join(link): case let .join(link):
controller.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in controller.present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in
openResolvedPeerImpl(peerId, .chat(textInputState: nil, messageId: nil)) openResolvedPeerImpl(peerId, .chat(textInputState: nil, subject: nil))
}), in: .window(.root)) }), in: .window(.root))
default: default:
break break

View File

@ -248,9 +248,9 @@ private func resolveInternalUrl(account: Account, url: ParsedInternalUrl) -> Sig
} }
} else { } else {
if let peer = peer as? TelegramUser, peer.botInfo == nil { if let peer = peer as? TelegramUser, peer.botInfo == nil {
return .peer(peer.id, .chat(textInputState: nil, messageId: nil)) return .peer(peer.id, .chat(textInputState: nil, subject: nil))
} else { } else {
return .peer(peer.id, .chat(textInputState: nil, messageId: nil)) return .peer(peer.id, .chat(textInputState: nil, subject: nil))
} }
} }
} else { } else {
@ -263,7 +263,7 @@ private func resolveInternalUrl(account: Account, url: ParsedInternalUrl) -> Sig
} }
|> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in |> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in
if let peer = peer { if let peer = peer {
return .single(.peer(peer.id, .chat(textInputState: nil, messageId: nil))) return .single(.peer(peer.id, .chat(textInputState: nil, subject: nil)))
} else { } else {
return .single(.inaccessiblePeer) return .single(.inaccessiblePeer)
} }
@ -274,12 +274,12 @@ private func resolveInternalUrl(account: Account, url: ParsedInternalUrl) -> Sig
} }
|> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in |> mapToSignal { peer -> Signal<ResolvedUrl?, NoError> in
if let peer = peer { if let peer = peer {
return .single(.peer(peer.id, .chat(textInputState: nil, messageId: messageId))) return .single(.peer(peer.id, .chat(textInputState: nil, subject: .message(messageId))))
} else { } else {
return findChannelById(postbox: account.postbox, network: account.network, channelId: messageId.peerId.id) return findChannelById(postbox: account.postbox, network: account.network, channelId: messageId.peerId.id)
|> map { foundPeer -> ResolvedUrl? in |> map { foundPeer -> ResolvedUrl? in
if let foundPeer = foundPeer { if let foundPeer = foundPeer {
return .peer(foundPeer.id, .chat(textInputState: nil, messageId: messageId)) return .peer(foundPeer.id, .chat(textInputState: nil, subject: .message(messageId)))
} else { } else {
return .inaccessiblePeer return .inaccessiblePeer
} }