diff --git a/SiriIntents/IntentMessages.swift b/SiriIntents/IntentMessages.swift index cbbc6aec54..b059f14e8c 100644 --- a/SiriIntents/IntentMessages.swift +++ b/SiriIntents/IntentMessages.swift @@ -31,7 +31,7 @@ func unreadMessages(account: Account) -> Signal<[INMessage], NoError> { } if !isMuted && hasUnread { - signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(index.messageIndex.id.peerId), anchor: .upperBound, count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tagMask: nil, excludeNamespaces: [Namespaces.Message.CloudScheduled], orderStatistics: .combinedLocation) + signals.append(account.postbox.aroundMessageHistoryViewForLocation(.peer(index.messageIndex.id.peerId), anchor: .upperBound, count: 10, fixedCombinedReadStates: fixedCombinedReadStates, topTaggedMessageIdNamespaces: Set(), tagMask: nil, excludeNamespaces: [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal], orderStatistics: .combinedLocation) |> take(1) |> map { view -> [INMessage] in var messages: [INMessage] = [] diff --git a/submodules/AccountContext/Sources/ChatHistoryLocation.swift b/submodules/AccountContext/Sources/ChatHistoryLocation.swift index f339694d0f..5541df6c25 100644 --- a/submodules/AccountContext/Sources/ChatHistoryLocation.swift +++ b/submodules/AccountContext/Sources/ChatHistoryLocation.swift @@ -12,7 +12,6 @@ public enum ChatHistoryLocation: Equatable { case InitialSearch(location: ChatHistoryInitialSearchLocation, count: Int) case Navigation(index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int) case Scroll(index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, sourceIndex: MessageHistoryAnchorIndex, scrollPosition: ListViewScrollPosition, animated: Bool) - case Scheduled } public struct ChatHistoryLocationInput: Equatable { diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index d18273ba99..52dc67ace8 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -369,10 +369,10 @@ public class GalleryController: ViewController { case .peerMessagesAtId: if let tags = tagsForMessage(message!) { var excludeNamespaces: [MessageId.Namespace] - if message!.id.namespace == Namespaces.Message.CloudScheduled { + if message!.id.namespace == Namespaces.Message.ScheduledCloud { excludeNamespaces = [Namespaces.Message.Cloud, Namespaces.Message.Local, Namespaces.Message.SecretIncoming] } else { - excludeNamespaces = [Namespaces.Message.CloudScheduled] + excludeNamespaces = [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal] } let view = context.account.postbox.aroundMessageHistoryViewForLocation(.peer(message!.id.peerId), anchor: .index(message!.index), count: 50, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tags, excludeNamespaces: excludeNamespaces, orderStatistics: [.combinedLocation]) diff --git a/submodules/TelegramCore/TelegramCore/AccountStateManagementUtils.swift b/submodules/TelegramCore/TelegramCore/AccountStateManagementUtils.swift index 8fd3202040..7f1fd5974a 100644 --- a/submodules/TelegramCore/TelegramCore/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/TelegramCore/AccountStateManagementUtils.swift @@ -1305,13 +1305,13 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo } updatedState.updatePeersNearby(peersNearby) case let .updateNewScheduledMessage(apiMessage): - if let message = StoreMessage(apiMessage: apiMessage, namespace: Namespaces.Message.CloudScheduled) { + if let message = StoreMessage(apiMessage: apiMessage, namespace: Namespaces.Message.ScheduledCloud) { updatedState.addMessages([message], location: .Random) } case let .updateDeleteScheduledMessages(peer, messages): var messageIds: [MessageId] = [] for message in messages { - messageIds.append(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.CloudScheduled, id: message)) + messageIds.append(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.ScheduledCloud, id: message)) } updatedState.deleteMessages(messageIds) default: diff --git a/submodules/TelegramCore/TelegramCore/AccountViewTracker.swift b/submodules/TelegramCore/TelegramCore/AccountViewTracker.swift index f88a700665..bef9977a45 100644 --- a/submodules/TelegramCore/TelegramCore/AccountViewTracker.swift +++ b/submodules/TelegramCore/TelegramCore/AccountViewTracker.swift @@ -914,7 +914,11 @@ public final class AccountViewTracker { } } - public func aroundMessageOfInterestHistoryViewForLocation(_ chatLocation: ChatLocation, count: Int, tagMask: MessageTags? = nil, excludeNamespaces: [MessageId.Namespace] = [Namespaces.Message.CloudScheduled], orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func scheduledMessagesViewForLocation(_ chatLocation: ChatLocation) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + return self.aroundMessageHistoryViewForLocation(chatLocation, index: .upperBound, anchorIndex: .upperBound, count: 100, fixedCombinedReadStates: nil, tagMask: nil, excludeNamespaces: [Namespaces.Message.Cloud, Namespaces.Message.Local], orderStatistics: []) + } + + public func aroundMessageOfInterestHistoryViewForLocation(_ chatLocation: ChatLocation, count: Int, tagMask: MessageTags? = nil, excludeNamespaces: [MessageId.Namespace] = [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal], orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { if let account = self.account { let signal = account.postbox.aroundMessageOfInterestHistoryViewForChatLocation(chatLocation, count: count, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, excludeNamespaces: excludeNamespaces, orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData)) return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal) @@ -923,7 +927,7 @@ public final class AccountViewTracker { } } - public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocation, count: Int, messageId: MessageId, tagMask: MessageTags? = nil, excludeNamespaces: [MessageId.Namespace] = [Namespaces.Message.CloudScheduled], orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocation, count: Int, messageId: MessageId, tagMask: MessageTags? = nil, excludeNamespaces: [MessageId.Namespace] = [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal], orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { if let account = self.account { let signal = account.postbox.aroundIdMessageHistoryViewForLocation(chatLocation, count: count, messageId: messageId, topTaggedMessageIdNamespaces: [Namespaces.Message.Cloud], tagMask: tagMask, excludeNamespaces: excludeNamespaces, orderStatistics: orderStatistics, additionalData: wrappedHistoryViewAdditionalData(chatLocation: chatLocation, additionalData: additionalData)) return wrappedMessageHistorySignal(chatLocation: chatLocation, signal: signal) @@ -932,7 +936,7 @@ public final class AccountViewTracker { } } - public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocation, index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags? = nil, excludeNamespaces: [MessageId.Namespace] = [Namespaces.Message.CloudScheduled], orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocation, index: MessageHistoryAnchorIndex, anchorIndex: MessageHistoryAnchorIndex, count: Int, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags? = nil, excludeNamespaces: [MessageId.Namespace] = [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal], orderStatistics: MessageHistoryViewOrderStatistics = [], additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { if let account = self.account { let inputAnchor: HistoryViewInputAnchor switch index { diff --git a/submodules/TelegramCore/TelegramCore/ApplyUpdateMessage.swift b/submodules/TelegramCore/TelegramCore/ApplyUpdateMessage.swift index ebc7238ebf..1bc9b25447 100644 --- a/submodules/TelegramCore/TelegramCore/ApplyUpdateMessage.swift +++ b/submodules/TelegramCore/TelegramCore/ApplyUpdateMessage.swift @@ -40,7 +40,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes var apiMessage: Api.Message? for resultMessage in result.messages { - if let id = resultMessage.id(namespace: message.scheduleTime != nil ? Namespaces.Message.CloudScheduled : Namespaces.Message.Cloud) { + if let id = resultMessage.id(namespace: message.scheduleTime != nil ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud) { if id.peerId == message.id.peerId { apiMessage = resultMessage break @@ -48,7 +48,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes } } - if let apiMessage = apiMessage, let id = apiMessage.id(namespace: message.scheduleTime != nil ? Namespaces.Message.CloudScheduled : Namespaces.Message.Cloud) { + if let apiMessage = apiMessage, let id = apiMessage.id(namespace: message.scheduleTime != nil ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud) { messageId = id.id } else { messageId = result.rawMessageIds.first @@ -85,7 +85,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes transaction.updateMessage(message.id, update: { currentMessage in let updatedId: MessageId if let messageId = messageId { - let namespace = message.scheduleTime != nil ? Namespaces.Message.CloudScheduled : Namespaces.Message.Cloud + let namespace = message.scheduleTime != nil ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud updatedId = MessageId(peerId: currentMessage.id.peerId, namespace: namespace, id: messageId) } else { updatedId = currentMessage.id diff --git a/submodules/TelegramCore/TelegramCore/EnqueueMessage.swift b/submodules/TelegramCore/TelegramCore/EnqueueMessage.swift index 099914b5fb..ac1022b9ee 100644 --- a/submodules/TelegramCore/TelegramCore/EnqueueMessage.swift +++ b/submodules/TelegramCore/TelegramCore/EnqueueMessage.swift @@ -329,13 +329,13 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, } if let peer = peer as? TelegramChannel { switch peer.info { - case let .broadcast(info): - attributes.append(ViewCountMessageAttribute(count: 1)) - if info.flags.contains(.messagesShouldHaveSignatures) { - attributes.append(AuthorSignatureMessageAttribute(signature: accountPeer.debugDisplayTitle)) - } - case .group: - break + case let .broadcast(info): + attributes.append(ViewCountMessageAttribute(count: 1)) + if info.flags.contains(.messagesShouldHaveSignatures) { + attributes.append(AuthorSignatureMessageAttribute(signature: accountPeer.debugDisplayTitle)) + } + case .group: + break } } @@ -386,7 +386,15 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, } } - storeMessages.append(StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: randomId, groupingKey: localGroupingKey, timestamp: timestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: localTags, forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: mediaList)) + var messageNamespace = Namespaces.Message.Local + for attribute in attributes { + if attribute is OutgoingScheduleInfoMessageAttribute { + messageNamespace = Namespaces.Message.ScheduledLocal + break + } + } + + storeMessages.append(StoreMessage(peerId: peerId, namespace: messageNamespace, globallyUniqueId: randomId, groupingKey: localGroupingKey, timestamp: timestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: localTags, forwardInfo: nil, authorId: authorId, text: text, attributes: attributes, media: mediaList)) case let .forward(source, grouping, requestedAttributes): let sourceMessage = transaction.getMessage(source) if let sourceMessage = sourceMessage, let author = sourceMessage.author ?? sourceMessage.peers[sourceMessage.id.peerId] { @@ -496,11 +504,14 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, authorId = account.peerId } + var messageNamespace = Namespaces.Message.Local var entitiesAttribute: TextEntitiesMessageAttribute? for attribute in attributes { if let attribute = attribute as? TextEntitiesMessageAttribute { entitiesAttribute = attribute - break + } + if attribute is OutgoingScheduleInfoMessageAttribute { + messageNamespace = Namespaces.Message.ScheduledLocal } } @@ -531,8 +542,8 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, if peerId.namespace == Namespaces.Peer.SecretChat { augmentedMediaList = augmentedMediaList.map(convertForwardedMediaForSecretChat) } - - storeMessages.append(StoreMessage(peerId: peerId, namespace: Namespaces.Message.Local, globallyUniqueId: randomId, groupingKey: localGroupingKey, timestamp: timestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: [], forwardInfo: forwardInfo, authorId: authorId, text: sourceMessage.text, attributes: attributes, media: augmentedMediaList)) + + storeMessages.append(StoreMessage(peerId: peerId, namespace: messageNamespace, globallyUniqueId: randomId, groupingKey: localGroupingKey, timestamp: timestamp, flags: flags, tags: tags, globalTags: globalTags, localTags: [], forwardInfo: forwardInfo, authorId: authorId, text: sourceMessage.text, attributes: attributes, media: augmentedMediaList)) } } } diff --git a/submodules/TelegramCore/TelegramCore/Holes.swift b/submodules/TelegramCore/TelegramCore/Holes.swift index 5d68614bfc..cc5eb728f7 100644 --- a/submodules/TelegramCore/TelegramCore/Holes.swift +++ b/submodules/TelegramCore/TelegramCore/Holes.swift @@ -151,7 +151,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH var implicitelyFillHole = false let minMaxRange: ClosedRange - if namespace == Namespaces.Message.CloudScheduled { + if namespace == Namespaces.Message.ScheduledCloud { switch direction { case .aroundId, .range: implicitelyFillHole = true diff --git a/submodules/TelegramCore/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift b/submodules/TelegramCore/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift index c8c00c8453..3644676d6f 100644 --- a/submodules/TelegramCore/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift +++ b/submodules/TelegramCore/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift @@ -167,7 +167,7 @@ private func removeMessages(postbox: Postbox, network: Network, stateManager: Ac } else { var isScheduled = false for id in operation.messageIds { - if id.namespace == Namespaces.Message.CloudScheduled { + if id.namespace == Namespaces.Message.ScheduledCloud { isScheduled = true break } diff --git a/submodules/TelegramCore/TelegramCore/Namespaces.swift b/submodules/TelegramCore/TelegramCore/Namespaces.swift index 370ebee91d..352a42aef6 100644 --- a/submodules/TelegramCore/TelegramCore/Namespaces.swift +++ b/submodules/TelegramCore/TelegramCore/Namespaces.swift @@ -10,7 +10,8 @@ public struct Namespaces { public static let Cloud: Int32 = 0 public static let Local: Int32 = 1 public static let SecretIncoming: Int32 = 2 - public static let CloudScheduled: Int32 = 3 + public static let ScheduledCloud: Int32 = 3 + public static let ScheduledLocal: Int32 = 4 } public struct Media { diff --git a/submodules/TelegramCore/TelegramCore/PendingMessageManager.swift b/submodules/TelegramCore/TelegramCore/PendingMessageManager.swift index 1fd862eec7..643fd4a5fe 100644 --- a/submodules/TelegramCore/TelegramCore/PendingMessageManager.swift +++ b/submodules/TelegramCore/TelegramCore/PendingMessageManager.swift @@ -615,6 +615,7 @@ public final class PendingMessageManager { } else if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { var isForward = false var replyMessageId: Int32? + var scheduleTime: Int32? var flags: Int32 = 0 @@ -627,6 +628,9 @@ public final class PendingMessageManager { if attribute.flags.contains(.muted) { flags |= Int32(1 << 5) } + } else if let attribute = attribute as? OutgoingScheduleInfoMessageAttribute { + flags |= Int32(1 << 10) + scheduleTime = attribute.scheduleTime } } @@ -707,7 +711,7 @@ public final class PendingMessageManager { } } - sendMessageRequest = network.request(Api.functions.messages.sendMultiMedia(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, multiMedia: singleMedias, scheduleDate: nil)) + sendMessageRequest = network.request(Api.functions.messages.sendMultiMedia(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, multiMedia: singleMedias, scheduleDate: scheduleTime)) } return sendMessageRequest @@ -927,7 +931,7 @@ public final class PendingMessageManager { |> map(NetworkRequestResult.result) case let .forward(sourceInfo): if let forwardSourceInfoAttribute = forwardSourceInfoAttribute, let sourcePeer = transaction.getPeer(forwardSourceInfoAttribute.messageId.peerId), let sourceInputPeer = apiInputPeer(sourcePeer) { - sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, scheduleDate: nil), tag: dependencyTag) + sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: sourceInputPeer, id: [sourceInfo.messageId.id], randomId: [uniqueId], toPeer: inputPeer, scheduleDate: scheduleTime), tag: dependencyTag) |> map(NetworkRequestResult.result) } else { sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "internal")) @@ -936,7 +940,7 @@ public final class PendingMessageManager { if chatContextResult.hideVia { flags |= Int32(1 << 11) } - sendMessageRequest = network.request(Api.functions.messages.sendInlineBotResult(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, randomId: uniqueId, queryId: chatContextResult.queryId, id: chatContextResult.id, scheduleDate: nil)) + sendMessageRequest = network.request(Api.functions.messages.sendInlineBotResult(flags: flags, peer: inputPeer, replyToMsgId: replyMessageId, randomId: uniqueId, queryId: chatContextResult.queryId, id: chatContextResult.id, scheduleDate: scheduleTime)) |> map(NetworkRequestResult.result) case .messageScreenshot: sendMessageRequest = network.request(Api.functions.messages.sendScreenshotNotification(peer: inputPeer, replyToMsgId: replyMessageId ?? 0, randomId: uniqueId)) diff --git a/submodules/TelegramCore/TelegramCore/RequestEditMessage.swift b/submodules/TelegramCore/TelegramCore/RequestEditMessage.swift index 2b87216f91..beec16bf19 100644 --- a/submodules/TelegramCore/TelegramCore/RequestEditMessage.swift +++ b/submodules/TelegramCore/TelegramCore/RequestEditMessage.swift @@ -151,7 +151,7 @@ private func requestEditMessageInternal(account: Account, messageId: MessageId, } var effectiveScheduleTime: Int32? - if messageId.namespace == Namespaces.Message.CloudScheduled { + if messageId.namespace == Namespaces.Message.ScheduledCloud { if let scheduleTime = scheduleTime { effectiveScheduleTime = scheduleTime } else { diff --git a/submodules/TelegramCore/TelegramCore/UpdatesApiUtils.swift b/submodules/TelegramCore/TelegramCore/UpdatesApiUtils.swift index 1a60315b7f..2439756d55 100644 --- a/submodules/TelegramCore/TelegramCore/UpdatesApiUtils.swift +++ b/submodules/TelegramCore/TelegramCore/UpdatesApiUtils.swift @@ -116,7 +116,7 @@ extension Api.Message { switch toId { case let .peerUser(userId): let id: PeerId.Id - if namespace == Namespaces.Message.CloudScheduled { + if namespace == Namespaces.Message.ScheduledCloud { id = userId } else { id = (flags & Int32(2)) != 0 ? userId : (fromId ?? userId) diff --git a/submodules/TelegramUI/TelegramUI/ChatController.swift b/submodules/TelegramUI/TelegramUI/ChatController.swift index 19038b69c0..bf2a675b4c 100644 --- a/submodules/TelegramUI/TelegramUI/ChatController.swift +++ b/submodules/TelegramUI/TelegramUI/ChatController.swift @@ -517,7 +517,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } var actions = actions - if message.id.namespace != Namespaces.Message.CloudScheduled { + if ![Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal].contains(message.id.namespace) { actions.insert(.action(ContextMenuActionItem(text: "Reaction", icon: { _ in nil }, action: { _, f in guard let strongSelf = self else { return @@ -2768,7 +2768,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { var isScheduled = false for id in messageIds { - if id.namespace == Namespaces.Message.CloudScheduled { + if [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal].contains(id.namespace) { isScheduled = true break } diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift index c46ea1d3ed..51db01809d 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryGridNode.swift @@ -259,7 +259,7 @@ public final class ChatHistoryGridNode: GridNode, ChatHistoryNode { let historyViewUpdate = self.chatHistoryLocation |> distinctUntilChanged |> mapToSignal { location in - return chatHistoryViewForLocation(ChatHistoryLocationInput(content: location, id: 0), account: context.account, chatLocation: .peer(peerId), fixedCombinedReadStates: nil, tagMask: tagMask, additionalData: [], orderStatistics: [.locationWithinMonth]) + return chatHistoryViewForLocation(ChatHistoryLocationInput(content: location, id: 0), account: context.account, chatLocation: .peer(peerId), scheduled: false, fixedCombinedReadStates: nil, tagMask: tagMask, additionalData: [], orderStatistics: [.locationWithinMonth]) } let previousView = Atomic(value: nil) diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift index f310d22dcb..fa94441913 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryListNode.swift @@ -504,12 +504,17 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } additionalData.append(.totalUnreadState) + var scheduled = false + if let subject = subject, case .scheduledMessages = subject { + scheduled = true + } + let currentViewVersion = Atomic(value: nil) let historyViewUpdate = self.chatHistoryLocationPromise.get() |> distinctUntilChanged |> mapToSignal { location in - return chatHistoryViewForLocation(location, account: context.account, chatLocation: chatLocation, fixedCombinedReadStates: fixedCombinedReadStates.with { $0 }, tagMask: tagMask, additionalData: additionalData) + return chatHistoryViewForLocation(location, account: context.account, chatLocation: chatLocation, scheduled: scheduled, fixedCombinedReadStates: fixedCombinedReadStates.with { $0 }, tagMask: tagMask, additionalData: additionalData) |> beforeNext { viewUpdate in switch viewUpdate { case let .HistoryView(view, _, _, _, _, _, _): @@ -573,14 +578,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Navigation(index: .message(lastEntry.index), anchorIndex: .message(lastEntry.index), count: historyMessageCount), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) } else { - if let subject = subject { - switch subject { - case let .message(messageId): - strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) - case .scheduledMessages: - strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Scheduled, id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) - } - + if let subject = subject, case let .message(messageId) = subject { + strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) } else { strongSelf.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Initial(count: 60), id: (strongSelf.chatHistoryLocationValue?.id).flatMap({ $0 + 1 }) ?? 0) } @@ -743,13 +742,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } }) - if let subject = subject { - switch subject { - case let .message(messageId): - self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: 0) - case .scheduledMessages: - self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Scheduled, id: 0) - } + if let subject = subject, case let .message(messageId) = subject { + self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .InitialSearch(location: .id(messageId), count: 60), id: 0) } else { self.chatHistoryLocationValue = ChatHistoryLocationInput(content: .Initial(count: 60), id: 0) } diff --git a/submodules/TelegramUI/TelegramUI/ChatHistoryViewForLocation.swift b/submodules/TelegramUI/TelegramUI/ChatHistoryViewForLocation.swift index b19ecb061d..94512dcb1d 100644 --- a/submodules/TelegramUI/TelegramUI/ChatHistoryViewForLocation.swift +++ b/submodules/TelegramUI/TelegramUI/ChatHistoryViewForLocation.swift @@ -7,7 +7,7 @@ import Display import AccountContext func preloadedChatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: Account, chatLocation: ChatLocation, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags?, additionalData: [AdditionalMessageHistoryViewData], orderStatistics: MessageHistoryViewOrderStatistics = []) -> Signal { - return chatHistoryViewForLocation(location, account: account, chatLocation: chatLocation, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, additionalData: additionalData, orderStatistics: orderStatistics) + return chatHistoryViewForLocation(location, account: account, chatLocation: chatLocation, scheduled: false, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, additionalData: additionalData, orderStatistics: orderStatistics) |> introduceError(Bool.self) |> mapToSignal { update -> Signal in switch update { @@ -25,238 +25,203 @@ func preloadedChatHistoryViewForLocation(_ location: ChatHistoryLocationInput, a |> restartIfError } -func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, account: Account, chatLocation: ChatLocation, fixedCombinedReadStates: MessageHistoryViewReadState?, tagMask: MessageTags?, additionalData: [AdditionalMessageHistoryViewData], orderStatistics: MessageHistoryViewOrderStatistics = []) -> Signal { - switch location.content { - case let .Initial(count): - var preloaded = false - var fadeIn = false - let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> - if let tagMask = tagMask { - signal = account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: .upperBound, anchorIndex: .upperBound, count: count, fixedCombinedReadStates: nil, tagMask: tagMask, orderStatistics: orderStatistics) +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 + let count = 100 + 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 { - signal = account.viewTracker.aroundMessageOfInterestHistoryViewForLocation(chatLocation, count: count, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) - } - return signal - |> 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 maxReadIndex = view.maxReadIndex, tagMask == nil { - let aroundIndex = maxReadIndex - scrollPosition = .unread(index: maxReadIndex) - - var targetIndex = 0 - for i in 0 ..< view.entries.count { - if view.entries[i].index >= aroundIndex { - targetIndex = i - break - } - } - - let maxIndex = targetIndex + count / 2 - let minIndex = targetIndex - count / 2 - if minIndex <= 0 && view.holeEarlier { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - if maxIndex >= targetIndex { - if view.holeLater { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - if view.holeEarlier { - var incomingCount: Int32 = 0 - inner: for entry in view.entries.reversed() { - if entry.message.flags.contains(.Incoming) { - incomingCount += 1 - } - } - if case let .peer(peerId) = chatLocation, let combinedReadStates = view.fixedReadStates, case let .peer(readStates) = combinedReadStates, let readState = readStates[peerId], readState.count == incomingCount { - } else { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - } - } - } else 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)) } - } - case let .InitialSearch(searchLocation, count): - var preloaded = false - var fadeIn = false - - let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> - switch searchLocation { - case let .index(index): - signal = account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: .message(index), anchorIndex: .message(index), count: count, fixedCombinedReadStates: nil, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) - case let .id(id): - signal = account.viewTracker.aroundIdMessageHistoryViewForLocation(chatLocation, count: count, messageId: id, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) - } - - return signal |> map { view, updateType, initialData -> ChatHistoryViewUpdate in - let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) + var scrollPosition: ChatHistoryViewScrollPosition? - let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData) +// 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)) +// } +// } - if preloaded { - return .HistoryView(view: view, type: .Generic(type: updateType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: combinedInitialData, id: location.id) - } else { - let anchorIndex = view.anchorIndex - - var targetIndex = 0 - for i in 0 ..< view.entries.count { - if anchorIndex.isLessOrEqual(to: view.entries[i].index) { - targetIndex = i - break - } - } - - if !view.entries.isEmpty { - let minIndex = max(0, targetIndex - count / 2) - let maxIndex = min(view.entries.count, targetIndex + count / 2) - if minIndex == 0 && view.holeEarlier { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - if maxIndex == view.entries.count && view.holeLater { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - } else if view.holeEarlier || view.holeLater { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - - var reportUpdateType: ChatHistoryViewUpdateType = .Initial(fadeIn: fadeIn) - if case .FillHole = updateType { - reportUpdateType = .Generic(type: updateType) - } - - preloaded = true - return .HistoryView(view: view, type: reportUpdateType, scrollPosition: .index(index: anchorIndex, position: .center(.bottom), directionHint: .Down, animated: false), flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id) - } - } - case let .Navigation(index, anchorIndex, count): - var first = true - return account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: index, anchorIndex: anchorIndex, count: count, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) |> map { view, updateType, initialData -> ChatHistoryViewUpdate in - let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) - - let genericType: ViewUpdateType - if first { - first = false - genericType = ViewUpdateType.UpdateVisible - } else { - genericType = updateType - } - return .HistoryView(view: view, type: .Generic(type: genericType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id) - } - case let .Scroll(index, anchorIndex, sourceIndex, scrollPosition, animated): - let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up - let chatScrollPosition = ChatHistoryViewScrollPosition.index(index: index, position: scrollPosition, directionHint: directionHint, animated: animated) - var first = true - return account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: index, anchorIndex: anchorIndex, count: 100, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) - |> map { view, updateType, initialData -> ChatHistoryViewUpdate in - let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) - - let genericType: ViewUpdateType - let scrollPosition: ChatHistoryViewScrollPosition? = first ? chatScrollPosition : nil - if first { - first = false - genericType = ViewUpdateType.UpdateVisible - } else { - genericType = updateType - } - return .HistoryView(view: view, type: .Generic(type: genericType), scrollPosition: scrollPosition, flashIndicators: animated, originalScrollPosition: chatScrollPosition, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id) - } - case .Scheduled: - var preloaded = false - var fadeIn = false - let count = 100 - let signal = account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: .upperBound, anchorIndex: .upperBound, count: count, fixedCombinedReadStates: nil, tagMask: tagMask, excludeNamespaces: [Namespaces.Message.Cloud, Namespaces.Message.Local], orderStatistics: orderStatistics) - return signal - |> 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 maxReadIndex = view.maxReadIndex, tagMask == nil { - let aroundIndex = maxReadIndex - scrollPosition = .unread(index: maxReadIndex) - - var targetIndex = 0 - for i in 0 ..< view.entries.count { - if view.entries[i].index >= aroundIndex { - targetIndex = i - break - } - } - - let maxIndex = targetIndex + count / 2 - let minIndex = targetIndex - count / 2 - if minIndex <= 0 && view.holeEarlier { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - if maxIndex >= targetIndex { - if view.holeLater { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - if view.holeEarlier { - var incomingCount: Int32 = 0 - inner: for entry in view.entries.reversed() { - if entry.message.flags.contains(.Incoming) { - incomingCount += 1 - } - } - if case let .peer(peerId) = chatLocation, let combinedReadStates = view.fixedReadStates, case let .peer(readStates) = combinedReadStates, let readState = readStates[peerId], readState.count == incomingCount { - } else { - fadeIn = true - return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) - } - } - } - } else 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) - } + 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) } } + } else { + switch location.content { + case let .Initial(count): + var preloaded = false + var fadeIn = false + let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> + if let tagMask = tagMask { + signal = account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: .upperBound, anchorIndex: .upperBound, count: count, fixedCombinedReadStates: nil, tagMask: tagMask, orderStatistics: orderStatistics) + } else { + signal = account.viewTracker.aroundMessageOfInterestHistoryViewForLocation(chatLocation, count: count, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) + } + return signal + |> 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 maxReadIndex = view.maxReadIndex, tagMask == nil { + let aroundIndex = maxReadIndex + scrollPosition = .unread(index: maxReadIndex) + + var targetIndex = 0 + for i in 0 ..< view.entries.count { + if view.entries[i].index >= aroundIndex { + targetIndex = i + break + } + } + + let maxIndex = targetIndex + count / 2 + let minIndex = targetIndex - count / 2 + if minIndex <= 0 && view.holeEarlier { + fadeIn = true + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) + } + if maxIndex >= targetIndex { + if view.holeLater { + fadeIn = true + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) + } + if view.holeEarlier { + var incomingCount: Int32 = 0 + inner: for entry in view.entries.reversed() { + if entry.message.flags.contains(.Incoming) { + incomingCount += 1 + } + } + if case let .peer(peerId) = chatLocation, let combinedReadStates = view.fixedReadStates, case let .peer(readStates) = combinedReadStates, let readState = readStates[peerId], readState.count == incomingCount { + } else { + fadeIn = true + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) + } + } + } + } else 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) + } + } + case let .InitialSearch(searchLocation, count): + var preloaded = false + var fadeIn = false + + let signal: Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> + switch searchLocation { + case let .index(index): + signal = account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: .message(index), anchorIndex: .message(index), count: count, fixedCombinedReadStates: nil, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) + case let .id(id): + signal = account.viewTracker.aroundIdMessageHistoryViewForLocation(chatLocation, count: count, messageId: id, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) + } + + return signal |> 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 { + let anchorIndex = view.anchorIndex + + var targetIndex = 0 + for i in 0 ..< view.entries.count { + if anchorIndex.isLessOrEqual(to: view.entries[i].index) { + targetIndex = i + break + } + } + + if !view.entries.isEmpty { + let minIndex = max(0, targetIndex - count / 2) + let maxIndex = min(view.entries.count, targetIndex + count / 2) + if minIndex == 0 && view.holeEarlier { + fadeIn = true + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) + } + if maxIndex == view.entries.count && view.holeLater { + fadeIn = true + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) + } + } else if view.holeEarlier || view.holeLater { + fadeIn = true + return .Loading(initialData: combinedInitialData, type: .Generic(type: updateType)) + } + + var reportUpdateType: ChatHistoryViewUpdateType = .Initial(fadeIn: fadeIn) + if case .FillHole = updateType { + reportUpdateType = .Generic(type: updateType) + } + + preloaded = true + return .HistoryView(view: view, type: reportUpdateType, scrollPosition: .index(index: anchorIndex, position: .center(.bottom), directionHint: .Down, animated: false), flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id) + } + } + case let .Navigation(index, anchorIndex, count): + var first = true + return account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: index, anchorIndex: anchorIndex, count: count, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) |> map { view, updateType, initialData -> ChatHistoryViewUpdate in + let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) + + let genericType: ViewUpdateType + if first { + first = false + genericType = ViewUpdateType.UpdateVisible + } else { + genericType = updateType + } + return .HistoryView(view: view, type: .Generic(type: genericType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id) + } + case let .Scroll(index, anchorIndex, sourceIndex, scrollPosition, animated): + let directionHint: ListViewScrollToItemDirectionHint = sourceIndex > index ? .Down : .Up + let chatScrollPosition = ChatHistoryViewScrollPosition.index(index: index, position: scrollPosition, directionHint: directionHint, animated: animated) + var first = true + return account.viewTracker.aroundMessageHistoryViewForLocation(chatLocation, index: index, anchorIndex: anchorIndex, count: 100, fixedCombinedReadStates: fixedCombinedReadStates, tagMask: tagMask, orderStatistics: orderStatistics, additionalData: additionalData) + |> map { view, updateType, initialData -> ChatHistoryViewUpdate in + let (cachedData, cachedDataMessages, readStateData) = extractAdditionalData(view: view, chatLocation: chatLocation) + + let genericType: ViewUpdateType + let scrollPosition: ChatHistoryViewScrollPosition? = first ? chatScrollPosition : nil + if first { + first = false + genericType = ViewUpdateType.UpdateVisible + } else { + genericType = updateType + } + return .HistoryView(view: view, type: .Generic(type: genericType), scrollPosition: scrollPosition, flashIndicators: animated, originalScrollPosition: chatScrollPosition, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id) + } + } + } } private func extractAdditionalData(view: MessageHistoryView, chatLocation: ChatLocation) -> ( diff --git a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift index 73dbda7133..c27f4832ec 100644 --- a/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/TelegramUI/ChatInterfaceStateContextMenus.swift @@ -26,7 +26,7 @@ func canEditMessage(context: AccountContext, limitsConfiguration: LimitsConfigur var hasEditRights = false var unlimitedInterval = false - if message.id.namespace == Namespaces.Message.CloudScheduled { + if message.id.namespace == Namespaces.Message.ScheduledCloud { hasEditRights = true } else if message.id.peerId.namespace == Namespaces.Peer.SecretChat || message.id.namespace != Namespaces.Message.Cloud { hasEditRights = false @@ -283,7 +283,7 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState: canDeleteMessage = context.account.peerId == message.author?.id } - if message.id.namespace == Namespaces.Message.CloudScheduled { + if [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal].contains(message.id.namespace) { canReply = false canPin = false } @@ -721,7 +721,7 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me var hadPersonalIncoming = false var hadBanPeerId = false for id in messageIds { - let isScheduled = id.namespace == Namespaces.Message.CloudScheduled + let isScheduled = id.namespace == Namespaces.Message.ScheduledCloud if optionsMap[id] == nil { optionsMap[id] = [] } @@ -738,7 +738,7 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me optionsMap[id]!.insert(.rateCall) } } - if id.namespace == Namespaces.Message.CloudScheduled { + if id.namespace == Namespaces.Message.ScheduledCloud { optionsMap[id]!.insert(.sendScheduledNow) optionsMap[id]!.insert(.editScheduledTime) optionsMap[id]!.insert(.deleteLocally) diff --git a/submodules/TelegramUI/TelegramUI/ChatListItem.swift b/submodules/TelegramUI/TelegramUI/ChatListItem.swift index b59ee9be88..513d6122f0 100644 --- a/submodules/TelegramUI/TelegramUI/ChatListItem.swift +++ b/submodules/TelegramUI/TelegramUI/ChatListItem.swift @@ -643,7 +643,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { isPeerGroup = false isAd = isAdValue case let .groupReference(_, peers, messageValue, unreadState, hiddenByDefault): - if let messageValue = messageValue, !peers.isEmpty { + if let _ = messageValue, !peers.isEmpty { contentPeer = .chat(peers[0].peer) } else { contentPeer = .group(peers) diff --git a/submodules/TelegramUI/TelegramUI/PeerMessagesMediaPlaylist.swift b/submodules/TelegramUI/TelegramUI/PeerMessagesMediaPlaylist.swift index 77dd93692c..498479162c 100644 --- a/submodules/TelegramUI/TelegramUI/PeerMessagesMediaPlaylist.swift +++ b/submodules/TelegramUI/TelegramUI/PeerMessagesMediaPlaylist.swift @@ -486,7 +486,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { guard let message = message else { return .single(nil) } - return self.postbox.aroundMessageHistoryViewForLocation(.peer(peerId), anchor: .index(message.index), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, excludeNamespaces: [Namespaces.Message.CloudScheduled], orderStatistics: []) + return self.postbox.aroundMessageHistoryViewForLocation(.peer(peerId), anchor: .index(message.index), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, excludeNamespaces: [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal], orderStatistics: []) |> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in if let (message, aroundMessages, _) = navigatedMessageFromView(view.0, anchorIndex: message.index, position: .exact) { return .single((message, aroundMessages)) @@ -560,7 +560,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { } let historySignal = inputIndex |> mapToSignal { inputIndex -> Signal<(Message, [Message])?, NoError> in - return self.postbox.aroundMessageHistoryViewForLocation(.peer(peerId), anchor: .index(inputIndex), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, excludeNamespaces: [Namespaces.Message.CloudScheduled], orderStatistics: []) + return self.postbox.aroundMessageHistoryViewForLocation(.peer(peerId), anchor: .index(inputIndex), count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, excludeNamespaces: [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal], orderStatistics: []) |> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in let position: NavigatedMessageFromViewPosition switch navigation { @@ -590,7 +590,7 @@ final class PeerMessagesMediaPlaylist: SharedMediaPlaylist { } else { viewIndex = .lowerBound } - return self.postbox.aroundMessageHistoryViewForLocation(.peer(peerId), anchor: viewIndex, count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, excludeNamespaces: [Namespaces.Message.CloudScheduled], orderStatistics: []) + return self.postbox.aroundMessageHistoryViewForLocation(.peer(peerId), anchor: viewIndex, count: 10, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: [], tagMask: tagMask, excludeNamespaces: [Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal], orderStatistics: []) |> mapToSignal { view -> Signal<(Message, [Message])?, NoError> in let position: NavigatedMessageFromViewPosition switch navigation {