diff --git a/submodules/Postbox/Sources/MediaBox.swift b/submodules/Postbox/Sources/MediaBox.swift index a12e7a9b8f..555a608e95 100644 --- a/submodules/Postbox/Sources/MediaBox.swift +++ b/submodules/Postbox/Sources/MediaBox.swift @@ -929,6 +929,32 @@ public final class MediaBox { unlink(paths.partial + ".meta") self.fileContexts.removeValue(forKey: id) } + + let uniqueIds = Set(ids.map { $0.id.uniqueId }) + + var pathsToDelete: [String] = [] + + for cacheType in ["cache", "short-cache"] { + if let enumerator = FileManager.default.enumerator(at: URL(fileURLWithPath: "\(self.basePath)/\(cacheType)"), includingPropertiesForKeys: [], options: [.skipsSubdirectoryDescendants], errorHandler: nil) { + while let item = enumerator.nextObject() { + guard let url = item as? NSURL, let path = url.path, let fileName = url.lastPathComponent else { + continue + } + + if let range = fileName.range(of: ":") { + let resourceId = String(fileName[fileName.startIndex ..< range.lowerBound]) + if uniqueIds.contains(resourceId) { + pathsToDelete.append(path) + } + } + } + } + } + + for path in pathsToDelete { + unlink(path) + } + subscriber.putCompletion() } return EmptyDisposable diff --git a/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift index dc9f3f6f5f..ce6e9e6b7d 100644 --- a/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/AccountStateManagementUtils.swift @@ -2278,18 +2278,26 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP } } case let .DeleteMessagesWithGlobalIds(ids): + var resourceIds: [WrappedMediaResourceId] = [] transaction.deleteMessagesWithGlobalIds(ids, forEachMedia: { media in - processRemovedMedia(mediaBox, media) + addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds) }) + if !resourceIds.isEmpty { + let _ = mediaBox.removeCachedResources(Set(resourceIds)).start() + } case let .DeleteMessages(ids): deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: ids) case let .UpdateMinAvailableMessage(id): if let message = transaction.getMessage(id) { updatePeerChatInclusionWithMinTimestamp(transaction: transaction, id: id.peerId, minTimestamp: message.timestamp, forceRootGroupIfNotExists: false) } + var resourceIds: [WrappedMediaResourceId] = [] transaction.deleteMessagesInRange(peerId: id.peerId, namespace: id.namespace, minId: 1, maxId: id.id, forEachMedia: { media in - processRemovedMedia(mediaBox, media) + addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds) }) + if !resourceIds.isEmpty { + let _ = mediaBox.removeCachedResources(Set(resourceIds)).start() + } case let .UpdatePeerChatInclusion(peerId, groupId, changedGroup): let currentInclusion = transaction.getPeerChatListInclusion(peerId) var currentPinningIndex: UInt16? diff --git a/submodules/TelegramCore/Sources/DeleteMessages.swift b/submodules/TelegramCore/Sources/DeleteMessages.swift index e271570313..14dfab3fd3 100644 --- a/submodules/TelegramCore/Sources/DeleteMessages.swift +++ b/submodules/TelegramCore/Sources/DeleteMessages.swift @@ -4,48 +4,64 @@ import SwiftSignalKit import SyncCore -private func removeMessageMedia(message: Message, mediaBox: MediaBox) { - for media in message.media { - if let image = media as? TelegramMediaImage { - let _ = mediaBox.removeCachedResources(Set(image.representations.map({ WrappedMediaResourceId($0.resource.id) }))).start() - } else if let file = media as? TelegramMediaFile { - let _ = mediaBox.removeCachedResources(Set(file.previewRepresentations.map({ WrappedMediaResourceId($0.resource.id) }))).start() - let _ = mediaBox.removeCachedResources(Set([WrappedMediaResourceId(file.resource.id)])).start() +func addMessageMediaResourceIdsToRemove(media: Media, resourceIds: inout [WrappedMediaResourceId]) { + if let image = media as? TelegramMediaImage { + for representation in image.representations { + resourceIds.append(WrappedMediaResourceId(representation.resource.id)) } + } else if let file = media as? TelegramMediaFile { + for representation in file.previewRepresentations { + resourceIds.append(WrappedMediaResourceId(representation.resource.id)) + } + resourceIds.append(WrappedMediaResourceId(file.resource.id)) + } +} + +func addMessageMediaResourceIdsToRemove(message: Message, resourceIds: inout [WrappedMediaResourceId]) { + for media in message.media { + addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds) } } public func deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [MessageId], deleteMedia: Bool = true) { + var resourceIds: [WrappedMediaResourceId] = [] if deleteMedia { for id in ids { if id.peerId.namespace == Namespaces.Peer.SecretChat { if let message = transaction.getMessage(id) { - removeMessageMedia(message: message, mediaBox: mediaBox) + addMessageMediaResourceIdsToRemove(message: message, resourceIds: &resourceIds) } } } } - transaction.deleteMessages(ids, forEachMedia: { media in - if deleteMedia { - processRemovedMedia(mediaBox, media) - } + if !resourceIds.isEmpty { + let _ = mediaBox.removeCachedResources(Set(resourceIds)).start() + } + transaction.deleteMessages(ids, forEachMedia: { _ in }) } public func deleteAllMessagesWithAuthor(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, authorId: PeerId, namespace: MessageId.Namespace) { + var resourceIds: [WrappedMediaResourceId] = [] transaction.removeAllMessagesWithAuthor(peerId, authorId: authorId, namespace: namespace, forEachMedia: { media in - processRemovedMedia(mediaBox, media) + addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds) }) + if !resourceIds.isEmpty { + let _ = mediaBox.removeCachedResources(Set(resourceIds)).start() + } } public func clearHistory(transaction: Transaction, mediaBox: MediaBox, peerId: PeerId, namespaces: MessageIdNamespaces) { if peerId.namespace == Namespaces.Peer.SecretChat { + var resourceIds: [WrappedMediaResourceId] = [] transaction.withAllMessages(peerId: peerId, { message in - removeMessageMedia(message: message, mediaBox: mediaBox) + addMessageMediaResourceIdsToRemove(message: message, resourceIds: &resourceIds) return true }) + if !resourceIds.isEmpty { + let _ = mediaBox.removeCachedResources(Set(resourceIds)).start() + } } - transaction.clearHistory(peerId, namespaces: namespaces, forEachMedia: { media in - processRemovedMedia(mediaBox, media) + transaction.clearHistory(peerId, namespaces: namespaces, forEachMedia: { _ in }) } diff --git a/submodules/TelegramCore/Sources/DeleteMessagesInteractively.swift b/submodules/TelegramCore/Sources/DeleteMessagesInteractively.swift index dd3c1fe45d..2d45771b69 100644 --- a/submodules/TelegramCore/Sources/DeleteMessagesInteractively.swift +++ b/submodules/TelegramCore/Sources/DeleteMessagesInteractively.swift @@ -147,9 +147,7 @@ public func clearAuthorHistory(account: Account, peerId: PeerId, memberId: PeerI |> `catch` { success -> Signal in if success { return account.postbox.transaction { transaction -> Void in - transaction.removeAllMessagesWithAuthor(peerId, authorId: memberId, namespace: Namespaces.Message.Cloud, forEachMedia: { media in - processRemovedMedia(account.postbox.mediaBox, media) - }) + deleteAllMessagesWithAuthor(transaction: transaction, mediaBox: account.postbox.mediaBox, peerId: peerId, authorId: memberId, namespace: Namespaces.Message.Cloud) } } else { return .complete() diff --git a/submodules/TelegramCore/Sources/ProcessRemovedMedia.swift b/submodules/TelegramCore/Sources/ProcessRemovedMedia.swift deleted file mode 100644 index 725c1fb04b..0000000000 --- a/submodules/TelegramCore/Sources/ProcessRemovedMedia.swift +++ /dev/null @@ -1,13 +0,0 @@ -import Foundation -import Postbox - -import SyncCore - -func processRemovedMedia(_ mediaBox: MediaBox, _ media: Media) { - if let image = media as? TelegramMediaImage { - let _ = mediaBox.removeCachedResources(Set(image.representations.map({ WrappedMediaResourceId($0.resource.id) }))).start() - } else if let file = media as? TelegramMediaFile { - let _ = mediaBox.removeCachedResources(Set(file.previewRepresentations.map({ WrappedMediaResourceId($0.resource.id) }))).start() - let _ = mediaBox.removeCachedResources(Set([WrappedMediaResourceId(file.resource.id)])).start() - } -} diff --git a/submodules/TelegramCore/Sources/ScheduledMessages.swift b/submodules/TelegramCore/Sources/ScheduledMessages.swift index d40720f44c..f8500bb722 100644 --- a/submodules/TelegramCore/Sources/ScheduledMessages.swift +++ b/submodules/TelegramCore/Sources/ScheduledMessages.swift @@ -104,9 +104,13 @@ func managedApplyPendingScheduledMessagesActions(postbox: Postbox, network: Netw }) |> then( postbox.transaction { transaction -> Void in + var resourceIds: [WrappedMediaResourceId] = [] transaction.deleteMessages([entry.id], forEachMedia: { media in - processRemovedMedia(postbox.mediaBox, media) + addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds) }) + if !resourceIds.isEmpty { + let _ = postbox.mediaBox.removeCachedResources(Set(resourceIds)).start() + } } |> ignoreValues ) diff --git a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift index 6ba93d2ea0..d8318d1860 100644 --- a/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/UpdateCachedPeerData.swift @@ -421,9 +421,13 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPeerId: PeerI }) if let minAvailableMessageId = minAvailableMessageId, minAvailableMessageIdUpdated { + var resourceIds: [WrappedMediaResourceId] = [] transaction.deleteMessagesInRange(peerId: peerId, namespace: minAvailableMessageId.namespace, minId: 1, maxId: minAvailableMessageId.id, forEachMedia: { media in - processRemovedMedia(postbox.mediaBox, media) + addMessageMediaResourceIdsToRemove(media: media, resourceIds: &resourceIds) }) + if !resourceIds.isEmpty { + let _ = postbox.mediaBox.removeCachedResources(Set(resourceIds)).start() + } } case .chatFull: break