Remove deleted messages from search results

This commit is contained in:
Ilya Laktyushin 2020-09-28 03:37:38 +04:00
parent 6176d4fdc1
commit c54dfcce23
7 changed files with 75 additions and 12 deletions

View File

@ -473,7 +473,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
filters = [.chats, .media, .links, .files, .music, .voice]
}
self.filterContainerNode.update(size: CGSize(width: layout.size.width - 40.0, height: 38.0), sideInset: layout.safeInsets.left - 20.0, filters: filters.map { .filter($0) }, selectedFilter: self.selectedFilterKey, transitionFraction: self.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
let overflowInset: CGFloat = 20.0
self.filterContainerNode.update(size: CGSize(width: layout.size.width - overflowInset * 2.0, height: 38.0), sideInset: layout.safeInsets.left - overflowInset, filters: filters.map { .filter($0) }, selectedFilter: self.selectedFilterKey, transitionFraction: self.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
if let selectedMessageIds = self.stateValue.selectedMessageIds {
var wasAdded = false
@ -527,6 +528,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
self.addSubnode(selectionPanelNode)
}
selectionPanelNode.selectedMessages = selectedMessageIds
let panelHeight = selectionPanelNode.update(layout: layout, presentationData: self.presentationData, transition: wasAdded ? .immediate : transition)
let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - panelHeight), size: CGSize(width: layout.size.width, height: panelHeight))
if wasAdded {

View File

@ -571,6 +571,8 @@ public func chatListSearchContainerPreparedTransition(from fromEntries: [ChatLis
private struct ChatListSearchListPaneNodeState: Equatable {
var expandLocalSearch: Bool = false
var expandGlobalSearch: Bool = false
var deletedMessageIds = Set<MessageId>()
var deletedGlobalMessageIds = Set<Int32>()
}
private func doesPeerMatchFilter(peer: Peer, filter: ChatListNodePeersFilter) -> Bool {
@ -661,6 +663,8 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
private let searchContextValue = Atomic<ChatListSearchMessagesContext?>(value: nil)
var searchCurrentMessages: [Message]?
private var deletedMessagesDisposable: Disposable?
private var searchQueryValue: String?
private var searchOptionsValue: ChatListSearchOptions?
@ -1108,6 +1112,11 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
if !foundRemotePeers.2 {
index = 0
for message in foundRemoteMessages.0.0 {
if searchState.deletedMessageIds.contains(message.id) {
continue
} else if message.id.namespace == Namespaces.Message.Cloud && searchState.deletedGlobalMessageIds.contains(message.id.id) {
continue
}
let headerId = listMessageDateHeaderId(timestamp: message.timestamp)
if firstHeaderId == nil {
firstHeaderId = headerId
@ -1561,6 +1570,30 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
}
})
}
self.deletedMessagesDisposable = (context.account.stateManager.deletedMessages
|> deliverOnMainQueue).start(next: { [weak self] messageIds in
if let strongSelf = self {
strongSelf.updateState { state in
var state = state
var deletedMessageIds = state.deletedMessageIds
var deletedGlobalMessageIds = state.deletedGlobalMessageIds
for messageId in messageIds {
switch messageId {
case let .messageId(id):
deletedMessageIds.insert(id)
case let .global(id):
deletedGlobalMessageIds.insert(id)
}
}
state.deletedMessageIds = deletedMessageIds
state.deletedGlobalMessageIds = deletedGlobalMessageIds
return state
}
}
})
}
deinit {
@ -1571,6 +1604,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
self.playlistPreloadDisposable?.dispose()
self.recentDisposable.dispose()
self.updatedRecentPeersDisposable.dispose()
self.deletedMessagesDisposable?.dispose()
}
override func didLoad() {

View File

@ -134,8 +134,8 @@ final class ChatListSearchMessageSelectionPanelNode: ASDisplayNode {
let width = layout.size.width
let insets = layout.insets(options: [])
let leftInset = insets.left
let rightInset = insets.left
let leftInset = insets.left + layout.safeInsets.left
let rightInset = insets.right + layout.safeInsets.right
let panelHeight: CGFloat
if case .regular = layout.metrics.widthClass, case .regular = layout.metrics.heightClass {

View File

@ -592,6 +592,7 @@ struct AccountReplayedFinalState {
let addedIncomingMessageIds: [MessageId]
let wasScheduledMessageIds: [MessageId]
let addedSecretMessageIds: [MessageId]
let deletedMessageIds: [DeletedMessageId]
let updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]]
let updatedWebpages: [MediaId: TelegramMediaWebpage]
let updatedCalls: [Api.PhoneCall]
@ -606,6 +607,7 @@ struct AccountReplayedFinalState {
struct AccountFinalStateEvents {
let addedIncomingMessageIds: [MessageId]
let wasScheduledMessageIds:[MessageId]
let deletedMessageIds: [DeletedMessageId]
let updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]]
let updatedWebpages: [MediaId: TelegramMediaWebpage]
let updatedCalls: [Api.PhoneCall]
@ -622,12 +624,13 @@ struct AccountFinalStateEvents {
let updatedOutgoingThreadReadStates: [MessageId: MessageId.Id]
var isEmpty: Bool {
return self.addedIncomingMessageIds.isEmpty && self.wasScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty
return self.addedIncomingMessageIds.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty
}
init(addedIncomingMessageIds: [MessageId] = [], wasScheduledMessageIds: [MessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:]) {
init(addedIncomingMessageIds: [MessageId] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:]) {
self.addedIncomingMessageIds = addedIncomingMessageIds
self.wasScheduledMessageIds = wasScheduledMessageIds
self.deletedMessageIds = deletedMessageIds
self.updatedTypingActivities = updatedTypingActivities
self.updatedWebpages = updatedWebpages
self.updatedCalls = updatedCalls
@ -647,6 +650,7 @@ struct AccountFinalStateEvents {
init(state: AccountReplayedFinalState) {
self.addedIncomingMessageIds = state.addedIncomingMessageIds
self.wasScheduledMessageIds = state.wasScheduledMessageIds
self.deletedMessageIds = state.deletedMessageIds
self.updatedTypingActivities = state.updatedTypingActivities
self.updatedWebpages = state.updatedWebpages
self.updatedCalls = state.updatedCalls
@ -686,6 +690,6 @@ struct AccountFinalStateEvents {
let externallyUpdatedPeerId = self.externallyUpdatedPeerId.union(other.externallyUpdatedPeerId)
let authorizationListUpdated = self.authorizationListUpdated || other.authorizationListUpdated
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated, updatedIncomingThreadReadStates: self.updatedIncomingThreadReadStates.merging(other.updatedIncomingThreadReadStates, uniquingKeysWith: { lhs, _ in lhs }))
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, deletedMessageIds: self.deletedMessageIds + other.deletedMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated, updatedIncomingThreadReadStates: self.updatedIncomingThreadReadStates.merging(other.updatedIncomingThreadReadStates, uniquingKeysWith: { lhs, _ in lhs }))
}
}

View File

@ -2207,6 +2207,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
var delayNotificatonsUntil: Int32?
var peerActivityTimestamps: [PeerId: Int32] = [:]
var syncChatListFilters = false
var deletedMessageIds: [DeletedMessageId] = []
var holesFromPreviousStateMessageIds: [MessageId] = []
var clearHolesFromPreviousStateForChannelMessagesWithPts: [PeerIdAndMessageNamespace: Int32] = [:]
@ -2235,7 +2236,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
}
}
var wasOpearationScheduledMessegeIds: [MessageId] = []
var wasOperationScheduledMessageIds: [MessageId] = []
var addedOperationIncomingMessageIds: [MessageId] = []
for operation in finalState.state.operations {
@ -2251,7 +2252,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
}
}
if message.flags.contains(.WasScheduled) {
wasOpearationScheduledMessegeIds.append(id)
wasOperationScheduledMessageIds.append(id)
}
}
}
@ -2263,9 +2264,9 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
var wasScheduledMessageIds:[MessageId] = []
var addedIncomingMessageIds: [MessageId] = []
if !wasOpearationScheduledMessegeIds.isEmpty {
let existingIds = transaction.filterStoredMessageIds(Set(wasOpearationScheduledMessegeIds))
for id in wasOpearationScheduledMessegeIds {
if !wasOperationScheduledMessageIds.isEmpty {
let existingIds = transaction.filterStoredMessageIds(Set(wasOperationScheduledMessageIds))
for id in wasOperationScheduledMessageIds {
if !existingIds.contains(id) {
wasScheduledMessageIds.append(id)
}
@ -2440,10 +2441,12 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
if !resourceIds.isEmpty {
let _ = mediaBox.removeCachedResources(Set(resourceIds)).start()
}
deletedMessageIds.append(contentsOf: ids.map { .global($0) })
case let .DeleteMessages(ids):
deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: ids, manualAddMessageThreadStatsDifference: { id, add, remove in
addMessageThreadStatsDifference(threadMessageId: id, remove: remove, addedMessagePeer: nil, addedMessageId: nil, isOutgoing: false)
})
deletedMessageIds.append(contentsOf: ids.map { .messageId($0) })
case let .UpdateMinAvailableMessage(id):
if let message = transaction.getMessage(id) {
updatePeerChatInclusionWithMinTimestamp(transaction: transaction, id: id.peerId, minTimestamp: message.timestamp, forceRootGroupIfNotExists: false)
@ -3316,5 +3319,5 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
requestChatListFiltersSync(transaction: transaction)
}
return AccountReplayedFinalState(state: finalState, addedIncomingMessageIds: addedIncomingMessageIds, wasScheduledMessageIds: wasScheduledMessageIds, addedSecretMessageIds: addedSecretMessageIds, updatedTypingActivities: updatedTypingActivities, updatedWebpages: updatedWebpages, updatedCalls: updatedCalls, addedCallSignalingData: addedCallSignalingData, updatedPeersNearby: updatedPeersNearby, isContactUpdates: isContactUpdates, delayNotificatonsUntil: delayNotificatonsUntil, updatedIncomingThreadReadStates: updatedIncomingThreadReadStates, updatedOutgoingThreadReadStates: updatedOutgoingThreadReadStates)
return AccountReplayedFinalState(state: finalState, addedIncomingMessageIds: addedIncomingMessageIds, wasScheduledMessageIds: wasScheduledMessageIds, addedSecretMessageIds: addedSecretMessageIds, deletedMessageIds: deletedMessageIds, updatedTypingActivities: updatedTypingActivities, updatedWebpages: updatedWebpages, updatedCalls: updatedCalls, addedCallSignalingData: addedCallSignalingData, updatedPeersNearby: updatedPeersNearby, isContactUpdates: isContactUpdates, delayNotificatonsUntil: delayNotificatonsUntil, updatedIncomingThreadReadStates: updatedIncomingThreadReadStates, updatedOutgoingThreadReadStates: updatedOutgoingThreadReadStates)
}

View File

@ -46,6 +46,11 @@ private final class UpdatedPeersNearbySubscriberContext {
let subscribers = Bag<([PeerNearby]) -> Void>()
}
public enum DeletedMessageId: Hashable {
case global(Int32)
case messageId(MessageId)
}
public final class AccountStateManager {
private let queue = Queue()
private let accountPeerId: PeerId
@ -143,6 +148,11 @@ public final class AccountStateManager {
return self.threadReadStateUpdatesPipe.signal()
}
private let deletedMessagesPipe = ValuePipe<[DeletedMessageId]>()
public var deletedMessages: Signal<[DeletedMessageId], NoError> {
return self.deletedMessagesPipe.signal()
}
private var updatedWebpageContexts: [MediaId: UpdatedWebpageSubscriberContext] = [:]
private var updatedPeersNearbyContext = UpdatedPeersNearbySubscriberContext()
@ -740,6 +750,10 @@ public final class AccountStateManager {
if events.authorizationListUpdated {
self.authorizationListUpdatesPipe.putNext(Void())
}
if !events.deletedMessageIds.isEmpty {
self.deletedMessagesPipe.putNext(events.deletedMessageIds)
}
case let .pollCompletion(pollId, preMessageIds, preSubscribers):
if self.operations.count > 1 {
self.operations.removeFirst()
@ -1018,6 +1032,10 @@ public final class AccountStateManager {
}
}
func notifyDeletedMessages(messageIds: [MessageId]) {
self.deletedMessagesPipe.putNext(messageIds.map { .messageId($0) })
}
public func processIncomingCallUpdate(data: Data, completion: @escaping ((CallSessionRingingState, CallSession)?) -> Void) {
var rawData = data
let reader = BufferReader(Buffer(data: data))

View File

@ -90,6 +90,8 @@ func deleteMessagesInteractively(transaction: Transaction, stateManager: Account
}
deleteMessages(transaction: transaction, mediaBox: postbox.mediaBox, ids: messageIds)
stateManager?.notifyDeletedMessages(messageIds: messageIds)
if !uniqueIds.isEmpty && removeIfPossiblyDelivered {
stateManager?.removePossiblyDeliveredMessages(uniqueIds: uniqueIds)
}