Postbox -> TelegramEngine wave 26: resourceRangesStatus + removeCachedResources facades + sweep

Adds two TelegramEngine.Resources facades and migrates 4 Shape-A sites across 3 consumer files.
Also imports RangeSet in TelegramEngineResources.swift to disambiguate the RangeSet type from
Swift stdlib's iOS-18-only type.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
isaac 2026-04-21 04:18:03 +04:00
parent 939873f6f4
commit fa68639b25
5 changed files with 38 additions and 4 deletions

View file

@ -669,6 +669,31 @@ Net: 3 consumer files + 1 TelegramCore file + CLAUDE.md. TelegramEngineResources
Plan / record: (no plan doc this wave — mechanical sweep).
### Wave 26 outcome (2026-04-21)
`resourceRangesStatus` + `removeCachedResources` facade additions + consumer sweep. Combines two independent small sweeps into one commit.
**Two facades added:**
- `resourceRangesStatus(resource: EngineMediaResource) -> Signal<RangeSet<Int64>, NoError>` wraps the single `(MediaResource) -> Signal<RangeSet<Int64>, NoError>` overload. Takes `EngineMediaResource` (not `id:`) because Postbox's overload only accepts a resource, not an id — consumers pass `.resource` already. Facade unwraps via `_asResource()`.
- `removeCachedResources(ids: [EngineMediaResource.Id], force: Bool = false, notify: Bool = false) -> Signal<Float, NoError>` wraps the `([MediaResourceId], force:, notify:) -> Signal<Float, NoError>` overload. Maps ids internally.
**`import RangeSet` added to `TelegramEngineResources.swift`.** The `RangeSet<Int64>` return type caused a name collision with Swift stdlib's `RangeSet` (iOS 18+ only) until the local `RangeSet` module is imported. `TelegramCore/BUILD` already declared the dep at line 23 (`//submodules/Utils/RangeSet:RangeSet`), so no BUILD change needed.
**4 Shape-A consumer sites migrated (3 files):**
- `PhotoResources/Sources/PhotoResources.swift` (1)
- `TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryChatContent.swift` (1)
- `ChatListUI/Sources/ChatListSearchContainerNode.swift` (2)
For `ChatListSearchContainerNode.swift:1398`, the caller uses a `Set<MediaResourceId>` local — wave leaves the local as-is and maps at the call site via `resourceIds.map { EngineMediaResource.Id($0) }`. Migrating the local to `Set<EngineMediaResource.Id>` is out of scope (module keeps `import Postbox` for unrelated reasons).
**Build validation.** Clean build (563 processes, 265s, 0 errors) on the second attempt after adding `import RangeSet`.
**Lesson — Swift-stdlib-vs-third-party-module name collisions.** When a facade signature references a type name that exists both in Swift stdlib (potentially availability-restricted) and in a third-party module, the compiler picks the stdlib one by default. Fix: import the third-party module explicitly. In this codebase, `RangeSet` is provided by `submodules/Utils/RangeSet:RangeSet`, and TelegramCore already depends on it. Use `import RangeSet` at the file top.
Net: 3 consumer files + 1 TelegramCore file + CLAUDE.md. TelegramEngineResources.swift: +9 / -0 (including `import RangeSet`).
Plan / record: (no plan doc this wave — mechanical sweep).
### Modules currently free of `import Postbox` (running tally)
Consumer modules that no longer import Postbox, across all waves and standalone commits:

View file

@ -1104,7 +1104,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
f(.default)
return
}
let _ = (strongSelf.context.account.postbox.mediaBox.removeCachedResources([MediaResourceId(downloadResource.id)], notify: true)
let _ = (strongSelf.context.engine.resources.removeCachedResources(ids: [EngineMediaResource.Id(downloadResource.id)], notify: true)
|> deliverOnMainQueue).startStandalone(completed: {
f(.dismissWithoutContent)
})
@ -1395,7 +1395,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
}
}
let _ = (strongSelf.context.account.postbox.mediaBox.removeCachedResources(Array(resourceIds), force: true, notify: true)
let _ = (strongSelf.context.engine.resources.removeCachedResources(ids: resourceIds.map { EngineMediaResource.Id($0) }, force: true, notify: true)
|> deliverOnMainQueue).startStandalone(completed: {
guard let strongSelf = self else {
return

View file

@ -2076,7 +2076,7 @@ public func chatMessagePhotoStatus(context: AccountContext, messageId: MessageId
if let range = representationFetchRangeForDisplayAtSize(representation: largestRepresentation, dimension: displayAtSize) {
return combineLatest(
context.fetchManager.fetchStatus(category: .image, location: .chat(messageId.peerId), locationKey: .messageId(messageId), resource: largestRepresentation.resource),
context.account.postbox.mediaBox.resourceRangesStatus(largestRepresentation.resource)
context.engine.resources.resourceRangesStatus(resource: EngineMediaResource(largestRepresentation.resource))
)
|> map { status, rangeStatus -> MediaResourceStatus in
if rangeStatus.isSuperset(of: RangeSet<Int64>(range)) {

View file

@ -2,6 +2,7 @@ import Foundation
import SwiftSignalKit
import Postbox
import TelegramApi
import RangeSet
public enum MediaResourceUserContentType: UInt8, Equatable {
case other = 0
@ -484,5 +485,13 @@ public extension TelegramEngine {
public func copyResourceData(from: EngineMediaResource.Id, to: EngineMediaResource.Id, synchronous: Bool = false) {
self.account.postbox.mediaBox.copyResourceData(from: MediaResourceId(from.stringRepresentation), to: MediaResourceId(to.stringRepresentation), synchronous: synchronous)
}
public func resourceRangesStatus(resource: EngineMediaResource) -> Signal<RangeSet<Int64>, NoError> {
return self.account.postbox.mediaBox.resourceRangesStatus(resource._asResource())
}
public func removeCachedResources(ids: [EngineMediaResource.Id], force: Bool = false, notify: Bool = false) -> Signal<Float, NoError> {
return self.account.postbox.mediaBox.removeCachedResources(ids.map { MediaResourceId($0.stringRepresentation) }, force: force, notify: notify)
}
}
}

View file

@ -2091,7 +2091,7 @@ public func waitUntilStoryMediaPreloaded(context: AccountContext, peerId: Engine
}
statusSignals.append(
context.account.postbox.mediaBox.resourceRangesStatus(file.resource)
context.engine.resources.resourceRangesStatus(resource: EngineMediaResource(file.resource))
|> filter { ranges in
if let fetchRange {
return ranges.isSuperset(of: RangeSet(fetchRange.0))