diff --git a/Telegram-iOS/en.lproj/Localizable.strings b/Telegram-iOS/en.lproj/Localizable.strings index 4771f22914..a45da3d3cd 100644 --- a/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram-iOS/en.lproj/Localizable.strings @@ -4609,8 +4609,11 @@ Any member of this group will be able to see messages in the channel."; "ScheduledMessages.SendNow" = "Send Now"; "ScheduledMessages.EditTime" = "Reschedule"; "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.BotActionUnavailable" = "This action will become available after the message is published."; "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."; "GroupInfo.Permissions.SlowmodeValue.Off" = "Off"; + +"Undo.ScheduledMessagesCleared" = "Scheduled messages cleared"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index d85b8eaa9b..e5808adeaf 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -179,7 +179,7 @@ public final class NavigateToChatControllerParams { public let chatController: ChatController? public let context: AccountContext public let chatLocation: ChatLocation - public let messageId: MessageId? + public let subject: ChatControllerSubject? public let botStart: ChatControllerInitialBotStart? public let updateTextInputState: ChatTextInputState? public let activateInput: Bool @@ -191,12 +191,12 @@ public final class NavigateToChatControllerParams { public let parentGroupId: PeerGroupId? 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.chatController = chatController self.context = context self.chatLocation = chatLocation - self.messageId = messageId + self.subject = subject self.botStart = botStart self.updateTextInputState = updateTextInputState self.activateInput = activateInput diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 52a97a46bd..7f119048aa 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -7,7 +7,7 @@ import SwiftSignalKit public enum ChatControllerInitialBotStartBehavior { case interactive - case automatic(returnToPeerId: PeerId) + case automatic(returnToPeerId: PeerId, scheduled: Bool) } public struct ChatControllerInitialBotStart { @@ -22,7 +22,7 @@ public struct ChatControllerInitialBotStart { public enum ChatControllerInteractionNavigateToPeer { case `default` - case chat(textInputState: ChatTextInputState?, messageId: MessageId?) + case chat(textInputState: ChatTextInputState?, subject: ChatControllerSubject?) case info case withBotStartPayload(ChatControllerInitialBotStart) } diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 9a62d8c8ff..21ea059670 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -570,7 +570,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, return } - let beginClear: (InteractiveMessagesDeletionType) -> Void = { type in + let beginClear: (InteractiveHistoryClearingType) -> Void = { type in guard let strongSelf = self else { 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) }, scrollToEndIfExists: scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [])) strongSelf.chatListDisplayNode.chatListNode.clearHighlightAnimated(true) diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index 602e896b6a..150ce02736 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -53,7 +53,7 @@ public final class HashtagSearchController: TelegramBaseController { if let strongSelf = self { strongSelf.openMessageFromSearchDisposable.set((storedMessageFromSearchPeer(account: strongSelf.context.account, peer: peer) |> deliverOnMainQueue).start(next: { actualPeerId in if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { - strongSelf.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), 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) diff --git a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift index e1d217d93d..0568bf986f 100644 --- a/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift +++ b/submodules/InstantPageUI/Sources/InstantPageControllerNode.swift @@ -1199,9 +1199,9 @@ final class InstantPageControllerNode: ASDisplayNode, UIScrollViewDelegate { strongSelf.loadProgress.set(1.0) strongSelf.context.sharedContext.openResolvedUrl(result, context: strongSelf.context, urlContext: .generic, navigationController: strongSelf.getNavigationController(), openPeer: { peerId, navigation in switch navigation { - case let .chat(_, messageId): + case let .chat(_, subject): 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): if let navigationController = strongSelf.getNavigationController() { diff --git a/submodules/TelegramUI/TelegramUI/ApplicationContext.swift b/submodules/TelegramUI/TelegramUI/ApplicationContext.swift index d4cc28d80b..107fb94ac1 100644 --- a/submodules/TelegramUI/TelegramUI/ApplicationContext.swift +++ b/submodules/TelegramUI/TelegramUI/ApplicationContext.swift @@ -787,7 +787,7 @@ final class AuthorizedApplicationContext { } 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 { @@ -832,7 +832,7 @@ final class AuthorizedApplicationContext { if visiblePeerId != peerId || messageId != nil { if self.rootController.rootTabController != nil { - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: self.rootController, context: self.context, chatLocation: .peer(peerId), 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 { self.scheduledOperChatWithPeerId = (peerId, messageId, activateInput) } diff --git a/submodules/TelegramUI/TelegramUI/ChatBotInfoItem.swift b/submodules/TelegramUI/TelegramUI/ChatBotInfoItem.swift index f307665b24..372cf9a173 100644 --- a/submodules/TelegramUI/TelegramUI/ChatBotInfoItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatBotInfoItem.swift @@ -301,7 +301,7 @@ final class ChatBotInfoItemNode: ListViewItemNode { case let .url(url, concealed): self.item?.controllerInteraction.openUrl(url, concealed, nil) 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): self.item?.controllerInteraction.openPeerMention(name) case let .botCommand(command): diff --git a/submodules/TelegramUI/TelegramUI/ChatButtonKeyboardInputNode.swift b/submodules/TelegramUI/TelegramUI/ChatButtonKeyboardInputNode.swift index 4b6c27902a..9a2f2c65f5 100644 --- a/submodules/TelegramUI/TelegramUI/ChatButtonKeyboardInputNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatButtonKeyboardInputNode.swift @@ -198,7 +198,7 @@ final class ChatButtonKeyboardInputNode: ChatInputNode { peerId = message.id.peerId } 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: diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index d36d08dc5f..a208bd5c22 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -319,6 +319,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var isScheduledMessages = false if let subject = subject, case .scheduledMessages = subject { + self.canReadHistory.set(false) isScheduledMessages = true } @@ -588,6 +589,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self, canSendMessagesToChat(strongSelf.presentationInterfaceState) else { 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({ if let strongSelf = self { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { @@ -659,6 +664,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return true }, requestMessageActionCallback: { [weak self] messageId, data, isGame in 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) { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { return $0.updatedTitlePanelContext { @@ -728,6 +738,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, requestMessageActionUrlAuth: { [weak self] defaultUrl, messageId, buttonId in 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) { strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, { return $0.updatedTitlePanelContext { @@ -845,10 +859,14 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self else { return } - if let botStart = strongSelf.botStart, case let .automatic(returnToPeerId) = botStart.behavior { - strongSelf.openPeer(peerId: returnToPeerId, navigation: .chat(textInputState: ChatTextInputState(inputText: NSAttributedString(string: inputString)), messageId: nil), fromMessage: nil) + 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 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 { - 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 if let strongSelf = self { @@ -856,6 +874,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, shareCurrentLocation: { [weak self] in 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: { if let strongSelf = self, let locationManager = strongSelf.context.sharedContext.locationManager { let _ = (currentLocationManagerCoordinate(manager: locationManager, timeout: 5.0) @@ -873,6 +895,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, shareAccountContact: { [weak self] in 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: { if let strongSelf = self { 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 actionSheet?.dismissAnimated() 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 { @@ -1458,7 +1484,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, sendScheduledMessagesNow: { [weak self] messageIds in if let strongSelf = self { - strongSelf.sendScheduledMessagesNow(messageIds) + let _ = sendScheduledMessageNowInteractively(postbox: strongSelf.context.account.postbox, messageId: messageIds.first!).start() } }, editScheduledMessagesTime: { [weak self] messageIds in if let strongSelf = self, let messageId = messageIds.first { @@ -2183,7 +2209,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var slowmodeState: ChatSlowmodeState? if let cachedData = combinedInitialData.cachedData as? CachedChannelData { 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) { 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 { 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 var options = transition.options let _ = options.insert(.Synchronous) @@ -2493,17 +2520,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) var maxInsertedItem: Int? + var insertedIndex: Int? var insertItems: [ListViewInsertItem] = [] for i in 0 ..< transition.insertItems.count { let item = transition.insertItems[i] if item.directionHint == .Down && (maxInsertedItem == nil || 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)) } 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) } @@ -2559,9 +2590,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } let _ = (enqueueMessages(account: strongSelf.context.account, peerId: peerId, messages: transformedMessages) - |> deliverOnMainQueue).start(next: { _ in + |> deliverOnMainQueue).start(next: { messageIds in 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 } 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 self?.navigationButtonAction(.openChatInfo) @@ -3132,7 +3166,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, botSwitchChatWithPayload: { [weak self] peerId, payload in 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 guard let strongSelf = self else { @@ -3921,7 +3955,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let actions: [TextAlertAction] if moreInfo { 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: {})] } else { 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 beginClear: (InteractiveMessagesDeletionType) -> Void = { [weak self] type in + let beginClear: (InteractiveHistoryClearingType) -> Void = { [weak self] type in guard let strongSelf = self else { return } @@ -4642,7 +4676,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.historyNode.historyAppearsCleared = true 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 } else { statusText = strongSelf.presentationData.strings.Undo_ChatCleared @@ -4661,16 +4697,21 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let actionSheet = ActionSheetController(presentationTheme: self.presentationData.theme) 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(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForEveryone(mainPeer.compactDisplayTitle).0, color: .destructive, action: { [weak actionSheet] in beginClear(.forEveryone) actionSheet?.dismissAnimated() })) items.append(ActionSheetButtonItem(title: self.presentationData.strings.ChatList_DeleteForCurrentUser, color: .destructive, action: { [weak actionSheet] in - beginClear(.forLocalPeer) actionSheet?.dismissAnimated() + beginClear(.forLocalPeer) })) } else { items.append(ActionSheetTextItem(title: text)) @@ -4876,13 +4917,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G 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)) - }, sendMessagesWithSignals: { [weak self] signals, silentPosting in + }, sendMessagesWithSignals: { [weak self] signals, mode in if !inputText.string.isEmpty { //strongSelf.clearInputText() } if editMediaOptions != nil { self?.editMessageMediaWithLegacySignals(signals!) } else { + var silentPosting = false + //if mode == self?.enqueueMediaMessages(signals: signals, silentPosting: silentPosting) } }, 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)) }) controller.descriptionGenerator = legacyAssetPickerItemGenerator() - controller.completionBlock = { [weak legacyController] signals, silentPosting in + controller.completionBlock = { [weak legacyController] signals, mode in if let legacyController = legacyController { legacyController.dismiss() + var silentPosting = false completion(signals!, silentPosting) } } @@ -5149,7 +5193,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) 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) { guard case let .peer(peerId) = self.chatLocation else { 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 { self.enqueueMediaMessageDisposable.set((legacyAssetPickerEnqueueMessages(account: self.context.account, signals: signals!) |> deliverOnMainQueue).start(next: { [weak self] messages in 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 strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ 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 { - 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) { if let fromIndex = fromIndex { @@ -5853,6 +5893,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.messageIndexDisposable.set(nil) self.chatDisplayNode.historyNode.scrollToMessage(from: fromIndex, to: message.index, animated: animated, scrollPosition: scrollPosition) 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 { self.loadingMessage.set(true) 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 { let _ = (self.context.account.postbox.transaction({ transaction -> Void in transaction.updatePeerChatInterfaceState(peerId, update: { currentState in @@ -6130,11 +6172,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) |> deliverOnMainQueue).start(completed: { [weak self] in 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 { - (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): (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 if case .default = navigation { 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)) @@ -6504,13 +6546,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } switch navigation { - case let .chat(_, messageId): + case let .chat(_, subject): 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)) } } 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: strongSelf.navigationActionDisposable.set((strongSelf.context.account.postbox.loadedPeerWithId(peerId) diff --git a/submodules/TelegramUI/TelegramUI/ChatEmptyNode.swift b/submodules/TelegramUI/TelegramUI/ChatEmptyNode.swift index 4a6914766f..3cfdd04a63 100644 --- a/submodules/TelegramUI/TelegramUI/ChatEmptyNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatEmptyNode.swift @@ -455,8 +455,8 @@ final class ChatEmptyNode: ASDisplayNode { } let contentType: ChatEmptyNodeContentType - if let peer = interfaceState.renderedPeer?.peer { - if peer.id == self.accountPeerId && !interfaceState.isScheduledMessages { + if let peer = interfaceState.renderedPeer?.peer, !interfaceState.isScheduledMessages { + if peer.id == self.accountPeerId { contentType = .cloud } else if let _ = peer as? TelegramSecretChat { contentType = .secret diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift index 6efa58a4db..733d040d61 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift @@ -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()) } - func scrollWithDeltaOffset(_ offset: CGFloat) { - - } - public func anchorMessageInCurrentHistoryView() -> Message? { if let historyView = self.historyView { if let visibleRange = self.displayedItemRange.visibleRange { diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryViewForLocation.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryViewForLocation.swift index ae12d1ee33..ceb3afdf85 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryViewForLocation.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryViewForLocation.swift @@ -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 { - if scheduled { - var preloaded = false - var fadeIn = false + var first = true + 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) |> map { view, updateType, initialData -> ChatHistoryViewUpdate in let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData) - if preloaded { - return .HistoryView(view: view, type: .Generic(type: updateType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: combinedInitialData, id: location.id) - } 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) + if view.isLoading { + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) } + + 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 { switch location.content { diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift index 9c1ba28f25..fcef87b219 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageAnimatedStickerItemNode.swift @@ -379,8 +379,12 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { avatarInset = 0.0 } + let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp()) + 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 { if let _ = attribute as? SourceReferenceMessageAttribute { needShareButton = true @@ -424,7 +428,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } var deliveryFailedInset: CGFloat = 0.0 - if item.content.firstMessage.flags.contains(.Failed) { + if isFailed { deliveryFailedInset += 24.0 } @@ -446,7 +450,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { if item.message.effectivelyIncoming(item.context.account.peerId) { statusType = .FreeIncoming } else { - if item.message.flags.contains(.Failed) { + if isFailed { statusType = .FreeOutgoing(.Failed) } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { statusType = .FreeOutgoing(.Sending) @@ -659,7 +663,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { strongSelf.replyInfoNode = nil } - if item.content.firstMessage.flags.contains(.Failed) { + if isFailed { let deliveryFailedNode: ChatMessageDeliveryFailedNode var isAppearing = false if let current = strongSelf.deliveryFailedNode { @@ -740,7 +744,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { var navigate: ChatControllerInteractionNavigateToPeer if item.content.firstMessage.id.peerId == item.context.account.peerId { - navigate = .chat(textInputState: nil, messageId: nil) + navigate = .chat(textInputState: nil, subject: nil) } else { navigate = .info } @@ -748,7 +752,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { for attribute in item.content.firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { openPeerId = attribute.messageId.peerId - navigate = .chat(textInputState: nil, messageId: attribute.messageId) + navigate = .chat(textInputState: nil, subject: .message(attribute.messageId)) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift index 56be379212..63243f3871 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageBubbleItemNode.swift @@ -666,8 +666,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { avatarInset = 0.0 } + let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp()) + var needShareButton = false - if item.message.flags.contains(.Failed) { + if isFailed { needShareButton = false } else if item.message.id.peerId == item.context.account.peerId { if let _ = sourceReference { @@ -731,7 +733,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { } var deliveryFailedInset: CGFloat = 0.0 - if item.content.firstMessage.flags.contains(.Failed) { + if isFailed { deliveryFailedInset += 24.0 } @@ -1032,7 +1034,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { if message.effectivelyIncoming(item.context.account.peerId) { statusType = .ImageIncoming } else { - if message.flags.contains(.Failed) { + if isFailed { statusType = .ImageOutgoing(.Failed) } else if message.flags.isSending && !message.isSentOrAcknowledged { statusType = .ImageOutgoing(.Sending) @@ -1587,7 +1589,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { 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 var isAppearing = false if let current = strongSelf.deliveryFailedNode { @@ -2133,7 +2136,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { var navigate: ChatControllerInteractionNavigateToPeer if item.content.firstMessage.id.peerId == item.context.account.peerId { - navigate = .chat(textInputState: nil, messageId: nil) + navigate = .chat(textInputState: nil, subject: nil) } else { navigate = .info } @@ -2141,7 +2144,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView { for attribute in item.content.firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { 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 case let .peerMention(peerId, _): 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 case let .textMention(name): foundTapAction = true diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift index 6758350385..f0763787e9 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageInstantVideoItemNode.swift @@ -580,7 +580,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { var navigate: ChatControllerInteractionNavigateToPeer if item.content.firstMessage.id.peerId == item.context.account.peerId { - navigate = .chat(textInputState: nil, messageId: nil) + navigate = .chat(textInputState: nil, subject: nil) } else { navigate = .info } @@ -588,7 +588,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView { for attribute in item.content.firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { openPeerId = attribute.messageId.peerId - navigate = .chat(textInputState: nil, 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) } 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 { item.controllerInteraction.displayMessageTooltip(item.message.id, item.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, forwardInfoNode, nil) } diff --git a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift index 262e137a64..eeb2a51b28 100644 --- a/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatMessageStickerItemNode.swift @@ -181,8 +181,10 @@ class ChatMessageStickerItemNode: ChatMessageItemView { avatarInset = 0.0 } + let isFailed = item.content.firstMessage.effectivelyFailed(timestamp: item.context.account.network.getApproximateRemoteTimestamp()) + var needShareButton = false - if item.message.flags.contains(.Failed) { + if isFailed { needShareButton = false } else if item.message.id.peerId == item.context.account.peerId { for attribute in item.content.firstMessage.attributes { @@ -228,7 +230,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { } var deliveryFailedInset: CGFloat = 0.0 - if item.content.firstMessage.flags.contains(.Failed) { + if isFailed { deliveryFailedInset += 24.0 } @@ -246,7 +248,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { if item.message.effectivelyIncoming(item.context.account.peerId) { statusType = .FreeIncoming } else { - if item.message.flags.contains(.Failed) { + if isFailed { statusType = .FreeOutgoing(.Failed) } else if item.message.flags.isSending && !item.message.isSentOrAcknowledged { statusType = .FreeOutgoing(.Sending) @@ -503,7 +505,8 @@ class ChatMessageStickerItemNode: ChatMessageItemView { strongSelf.replyInfoNode = nil } - if item.content.firstMessage.flags.contains(.Failed) { + + if isFailed { let deliveryFailedNode: ChatMessageDeliveryFailedNode var isAppearing = false if let current = strongSelf.deliveryFailedNode { @@ -584,7 +587,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { var navigate: ChatControllerInteractionNavigateToPeer if item.content.firstMessage.id.peerId == item.context.account.peerId { - navigate = .chat(textInputState: nil, messageId: nil) + navigate = .chat(textInputState: nil, subject: nil) } else { navigate = .info } @@ -592,7 +595,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { for attribute in item.content.firstMessage.attributes { if let attribute = attribute as? SourceReferenceMessageAttribute { openPeerId = attribute.messageId.peerId - navigate = .chat(textInputState: nil, messageId: attribute.messageId) + navigate = .chat(textInputState: nil, subject: .message(attribute.messageId)) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift b/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift index 5a0d87496f..58acf63749 100644 --- a/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift +++ b/submodules/TelegramUI/TelegramUI/ChatPresentationData.swift @@ -48,6 +48,8 @@ public final class ChatPresentationData { let nameDisplayOrder: PresentationPersonNameOrder let disableAnimations: Bool let largeEmoji: Bool + let animatedEmojiScale: CGFloat + let isPreview: Bool let messageFont: UIFont let messageEmojiFont1: UIFont @@ -59,9 +61,7 @@ public final class ChatPresentationData { let messageFixedFont: 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) { + init(theme: ChatPresentationThemeData, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool, largeEmoji: Bool, animatedEmojiScale: CGFloat = 1.0, isPreview: Bool = false) { self.theme = theme self.fontSize = fontSize self.strings = strings @@ -69,6 +69,7 @@ public final class ChatPresentationData { self.nameDisplayOrder = nameDisplayOrder self.disableAnimations = disableAnimations self.largeEmoji = largeEmoji + self.isPreview = isPreview let baseFontSize = fontSize.baseDisplaySize self.messageFont = UIFont.systemFont(ofSize: baseFontSize) diff --git a/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift index 65c1109da2..0e377b5f14 100644 --- a/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatRecentActionsControllerNode.swift @@ -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) case .botStart: break - //strongSelf.openPeer(peerId: peerId, navigation: .withBotStartPayload(ChatControllerInitialBotStart(payload: payload, behavior: .interactive)), fromMessage: nil) case .groupBotStart: break case let .channelMessage(peerId, messageId): 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): strongSelf.presentController(StickerPackPreviewController(context: strongSelf.context, stickerPack: .name(name), parentNavigationController: strongSelf.getNavigationController()), nil) diff --git a/submodules/TelegramUI/TelegramUI/ChatScheduleTimeControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatScheduleTimeControllerNode.swift index 2b5b3ebc45..37a54dc28b 100644 --- a/submodules/TelegramUI/TelegramUI/ChatScheduleTimeControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatScheduleTimeControllerNode.swift @@ -118,6 +118,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel strongSelf.updateMinimumDate() strongSelf.pickerView.layer.addShakeAnimation() } else { + strongSelf.doneButton.isUserInteractionEnabled = false strongSelf.completion?(Int32(strongSelf.pickerView.date.timeIntervalSince1970)) } } diff --git a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift index 64e78945e9..c3deda52ee 100644 --- a/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatSendMessageActionSheetControllerNode.swift @@ -23,7 +23,7 @@ private enum ChatSendMessageActionIcon { case .schedule: 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 separatorNode: ASDisplayNode + private let backgroundNode: ASDisplayNode private let highlightedBackgroundNode: ASDisplayNode private let buttonNode: HighlightTrackingButtonNode private let iconNode: ASImageNode @@ -46,21 +47,35 @@ private final class ActionSheetItemNode: ASDisplayNode { self.action = action 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.backgroundColor = theme.actionSheet.opaqueItemHighlightedBackgroundColor + self.highlightedBackgroundNode.isAccessibilityElement = false + self.highlightedBackgroundNode.backgroundColor = theme.contextMenu.itemHighlightedBackgroundColor self.highlightedBackgroundNode.alpha = 0.0 self.buttonNode = HighlightTrackingButtonNode() + self.buttonNode.isAccessibilityElement = true + self.buttonNode.accessibilityLabel = title self.titleNode = ImmediateTextNode() + self.titleNode.isAccessibilityElement = false 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.image = icon.image(theme: theme) self.iconNode.contentMode = .center + self.iconNode.isAccessibilityElement = false + self.iconNode.displaysAsynchronously = false + self.iconNode.displayWithoutProcessing = true + self.iconNode.isUserInteractionEnabled = false super.init() @@ -87,9 +102,10 @@ private final class ActionSheetItemNode: ASDisplayNode { } func updateTheme(_ theme: PresentationTheme) { - self.separatorNode.backgroundColor = theme.actionSheet.opaqueItemSeparatorColor - self.highlightedBackgroundNode.backgroundColor = theme.actionSheet.opaqueItemHighlightedBackgroundColor - self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.regular(17.0), textColor: theme.actionSheet.primaryTextColor) + self.separatorNode.backgroundColor = theme.contextMenu.itemSeparatorColor + self.backgroundNode.backgroundColor = theme.contextMenu.itemBackgroundColor + 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) if let maxWidth = self.maxWidth { @@ -180,11 +196,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.dimNode = ASDisplayNode() self.dimNode.alpha = 1.0 - if self.presentationData.theme.chatList.searchBarKeyboardColor == .light { - self.dimNode.backgroundColor = UIColor(white: 0.0, alpha: 0.04) - } else { - self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2) - } + self.dimNode.backgroundColor = self.presentationData.theme.contextMenu.dimColor self.sendButtonNode = HighlightableButtonNode() self.sendButtonNode.imageNode.displayWithoutProcessing = false @@ -205,8 +217,8 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.scrollNode.transform = CATransform3DMakeScale(1.0, -1.0, 1.0) self.contentContainerNode = ASDisplayNode() - self.contentContainerNode.backgroundColor = self.presentationData.theme.actionSheet.opaqueItemBackgroundColor - self.contentContainerNode.cornerRadius = 12.0 + self.contentContainerNode.backgroundColor = self.presentationData.theme.contextMenu.backgroundColor + self.contentContainerNode.cornerRadius = 14.0 self.contentContainerNode.clipsToBounds = true var contentNodes: [ActionSheetItemNode] = [] @@ -296,19 +308,18 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, } self.presentationData = presentationData - if self.presentationData.theme.chatList.searchBarKeyboardColor == .dark { - self.effectView.effect = UIBlurEffect(style: .dark) + if #available(iOS 9.0, *) { } 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 = UIColor(white: 0.0, alpha: 0.04) - } else { - self.dimNode.backgroundColor = presentationData.theme.chatList.backgroundColor.withAlphaComponent(0.2) - } + self.dimNode.backgroundColor = presentationData.theme.contextMenu.dimColor - 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.buttonCoverNode.backgroundColor = self.presentationData.theme.chat.inputPanel.panelBackgroundColor self.sendButtonNode.setImage(PresentationResourcesChat.chatInputPanelSendButtonImage(self.presentationData.theme), for: []) @@ -329,39 +340,14 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, func animateIn() { 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 self.presentationData.theme.chatList.searchBarKeyboardColor == .dark { - 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) - } - } + self.effectView.effect = makeCustomZoomBlurEffect() } else { self.effectView.alpha = 1.0 } - }, completion: { [weak self] _ in - guard let strongSelf = self else { - 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) + }, completion: { _ in }) + self.dimNode.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) @@ -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 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.contentContainerNode.layer.animatePosition(from: CGPoint(x: 160.0, y: 0.0), to: CGPoint(), duration: duration, timingFunction: kCAMediaTimingFunctionSpring, additive: true) - self.contentContainerNode.layer.animateScale(from: 0.45, to: 1.0, duration: duration, timingFunction: kCAMediaTimingFunctionSpring) + + let springDuration: Double = 0.42 + 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() }) - 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 }) if cancel { @@ -522,7 +510,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, let sideInset: CGFloat = 43.0 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)] = [] for itemNode in self.contentNodes { let (width, height, apply) = itemNode.updateLayout(maxWidth: layout.size.width - sideInset * 2.0) diff --git a/submodules/TelegramUI/TelegramUI/DebugController.swift b/submodules/TelegramUI/TelegramUI/DebugController.swift index 125465f295..0c96ed38dd 100644 --- a/submodules/TelegramUI/TelegramUI/DebugController.swift +++ b/submodules/TelegramUI/TelegramUI/DebugController.swift @@ -57,7 +57,6 @@ private enum DebugControllerEntry: ItemListNodeEntry { case resetData(PresentationTheme) case resetDatabase(PresentationTheme) case resetHoles(PresentationTheme) - case resetBiometricsData(PresentationTheme) case optimizeDatabase(PresentationTheme) case photoPreview(PresentationTheme, Bool) case knockoutWallpaper(PresentationTheme, Bool) @@ -74,7 +73,7 @@ private enum DebugControllerEntry: ItemListNodeEntry { return DebugControllerSection.logging.rawValue case .enableRaiseToSpeak, .keepChatNavigationStack, .skipReadHistory, .crashOnSlowQueries: 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 case .versionInfo: return DebugControllerSection.info.rawValue @@ -117,18 +116,16 @@ private enum DebugControllerEntry: ItemListNodeEntry { return 15 case .resetHoles: return 16 - case .resetBiometricsData: - return 17 case .optimizeDatabase: - return 18 + return 17 case .photoPreview: - return 19 + return 18 case .knockoutWallpaper: - return 21 + return 19 case .exportTheme: - return 22 + return 20 case .versionInfo: - return 23 + return 21 } } @@ -443,12 +440,6 @@ private enum DebugControllerEntry: ItemListNodeEntry { 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): return ItemListActionItem(theme: theme, title: "Optimize Database", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: { guard let context = arguments.context else { diff --git a/submodules/TelegramUI/TelegramUI/LegacyCamera.swift b/submodules/TelegramUI/TelegramUI/LegacyCamera.swift index b8af1a9efd..0dc3f57023 100644 --- a/submodules/TelegramUI/TelegramUI/LegacyCamera.swift +++ b/submodules/TelegramUI/TelegramUI/LegacyCamera.swift @@ -63,8 +63,9 @@ func presentedLegacyCamera(context: AccountContext, peer: Peer, cameraView: TGAt if peer is TelegramUser { controller.hasTimer = true } - controller.hasSilentPosting = true + controller.hasSilentPosting = !isSecretChat } + controller.hasSchedule = !isSecretChat let screenSize = parentController.view.bounds.size var startFrame = CGRect(x: 0, y: screenSize.height, width: screenSize.width, height: screenSize.height) diff --git a/submodules/TelegramUI/TelegramUI/NavigateToChatController.swift b/submodules/TelegramUI/TelegramUI/NavigateToChatController.swift index 48d8e757b3..fd99abd103 100644 --- a/submodules/TelegramUI/TelegramUI/NavigateToChatController.swift +++ b/submodules/TelegramUI/TelegramUI/NavigateToChatController.swift @@ -13,11 +13,11 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam var found = false var isFirst = true 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 { controller.updateTextInputState(updateTextInputState) } - if let messageId = params.messageId { + if let subject = params.subject, case let .message(messageId) = subject { let navigationController = params.navigationController let animated = params.animated controller.navigateToMessage(messageLocation: .id(messageId), animated: isFirst, completion: { [weak navigationController, weak controller] in @@ -60,7 +60,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam } } } 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 let resolvedKeepStack: Bool diff --git a/submodules/TelegramUI/TelegramUI/OpenResolvedUrl.swift b/submodules/TelegramUI/TelegramUI/OpenResolvedUrl.swift index c8e6f00fd6..97471f8e52 100644 --- a/submodules/TelegramUI/TelegramUI/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/TelegramUI/OpenResolvedUrl.swift @@ -18,9 +18,9 @@ private func defaultNavigationForPeerId(_ peerId: PeerId?, navigation: ChatContr if case .default = navigation { if let peerId = peerId { if peerId.namespace == Namespaces.Peer.CloudUser { - return .chat(textInputState: nil, messageId: nil) + return .chat(textInputState: nil, subject: nil) } else { - return .chat(textInputState: nil, messageId: nil) + return .chat(textInputState: nil, subject: nil) } } else { return .info @@ -81,7 +81,7 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur dismissInput() present(controller, ViewControllerPresentationArguments(presentationAnimation: ViewControllerPresentationAnimation.modalSheet)) case let .channelMessage(peerId, messageId): - openPeer(peerId, .chat(textInputState: nil, messageId: messageId)) + openPeer(peerId, .chat(textInputState: nil, subject: .message(messageId))) case let .stickerPack(name): dismissInput() 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): dismissInput() present(JoinLinkPreviewController(context: context, link: link, navigateToPeer: { peerId in - openPeer(peerId, .chat(textInputState: nil, messageId: nil)) + openPeer(peerId, .chat(textInputState: nil, subject: nil)) }), nil) case let .localization(identifier): dismissInput() diff --git a/submodules/TelegramUI/TelegramUI/OpenUrl.swift b/submodules/TelegramUI/TelegramUI/OpenUrl.swift index dff3178505..44bfd4fd27 100644 --- a/submodules/TelegramUI/TelegramUI/OpenUrl.swift +++ b/submodules/TelegramUI/TelegramUI/OpenUrl.swift @@ -198,10 +198,10 @@ func openExternalUrlImpl(context: AccountContext, urlContext: OpenURLContext, ur navigationController?.pushViewController(infoController) } }) - case let .chat(_, messageId): + case let .chat(_, subject): context.sharedContext.applicationBindings.dismissNativeController() 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): context.sharedContext.applicationBindings.dismissNativeController() diff --git a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift index f44edfbf6a..3eb05773a6 100644 --- a/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift +++ b/submodules/TelegramUI/TelegramUI/PeerMediaCollectionController.swift @@ -132,7 +132,7 @@ public class PeerMediaCollectionController: TelegramBaseController { ActionSheetButtonItem(title: strongSelf.presentationData.strings.SharedMedia_ViewInChat, color: .accent, action: { [weak actionSheet] in actionSheet?.dismissAnimated() 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 @@ -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 if let strongSelf = self { switch navigation { - case let .chat(_, messageId): + case let .chat(_, subject): 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: strongSelf.navigationActionDisposable.set((strongSelf.context.account.postbox.loadedPeerWithId(peerId) diff --git a/submodules/TelegramUI/TelegramUI/PeerMessagesMediaPlaylist.swift b/submodules/TelegramUI/TelegramUI/PeerMessagesMediaPlaylist.swift index 232b7875c7..54d2bbab4d 100644 --- a/submodules/TelegramUI/TelegramUI/PeerMessagesMediaPlaylist.swift +++ b/submodules/TelegramUI/TelegramUI/PeerMessagesMediaPlaylist.swift @@ -487,7 +487,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { self.loadingItem = true self.updateState() - let namespaces: HistoryViewNamespaces + let namespaces: MessageIdNamespaces if Namespaces.Message.allScheduled.contains(anchor.id.namespace) { namespaces = .just(Namespaces.Message.allScheduled) } else { diff --git a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping index dfbb09288b..48966ed8aa 100644 Binary files a/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping and b/submodules/TelegramUI/TelegramUI/Resources/PresentationStrings.mapping differ diff --git a/submodules/TelegramUI/TelegramUI/TextLinkHandling.swift b/submodules/TelegramUI/TelegramUI/TextLinkHandling.swift index b938b39131..cf65db921c 100644 --- a/submodules/TelegramUI/TelegramUI/TextLinkHandling.swift +++ b/submodules/TelegramUI/TelegramUI/TextLinkHandling.swift @@ -22,9 +22,9 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate 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 switch navigation { - case let .chat(_, messageId): + case let .chat(_, subject): 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: let peerSignal: Signal @@ -54,7 +54,7 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: PeerId?, navigate openResolvedPeerImpl(peerId, .default) case let .channelMessage(peerId, messageId): 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): 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)) case let .join(link): 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)) default: break diff --git a/submodules/TelegramUI/TelegramUI/UrlHandling.swift b/submodules/TelegramUI/TelegramUI/UrlHandling.swift index 9e818703f8..21df4622ad 100644 --- a/submodules/TelegramUI/TelegramUI/UrlHandling.swift +++ b/submodules/TelegramUI/TelegramUI/UrlHandling.swift @@ -248,9 +248,9 @@ private func resolveInternalUrl(account: Account, url: ParsedInternalUrl) -> Sig } } else { 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 { - return .peer(peer.id, .chat(textInputState: nil, messageId: nil)) + return .peer(peer.id, .chat(textInputState: nil, subject: nil)) } } } else { @@ -263,7 +263,7 @@ private func resolveInternalUrl(account: Account, url: ParsedInternalUrl) -> Sig } |> mapToSignal { peer -> Signal in 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 { return .single(.inaccessiblePeer) } @@ -274,12 +274,12 @@ private func resolveInternalUrl(account: Account, url: ParsedInternalUrl) -> Sig } |> mapToSignal { peer -> Signal in 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 { return findChannelById(postbox: account.postbox, network: account.network, channelId: messageId.peerId.id) |> map { foundPeer -> ResolvedUrl? in if let foundPeer = foundPeer { - return .peer(foundPeer.id, .chat(textInputState: nil, messageId: messageId)) + return .peer(foundPeer.id, .chat(textInputState: nil, subject: .message(messageId))) } else { return .inaccessiblePeer }