mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Postbox -> TelegramEngine wave 9: StorageUsageScreen preferences-view rewrite
Closes the first of the two future-wave candidates left open by wave 8 by
rewriting both AccountSpecificCacheStorageSettings preferences-view
observation sites in StorageUsageScreen.swift using engine APIs, and
drops import Postbox from that file.
Site 1 — cacheSettingsExceptionCount (former 1047-1087):
postbox.combinedView(keys: [.preferences(keys: Set([...]))]) +
PreferencesView ->
context.engine.data.subscribe(TelegramEngine.EngineData.Item
.Configuration.ApplicationSpecific-
Preference(key: ...))
+ preferencesEntry?.get(...)
Site 2 — peerExceptions (former 3131-3196):
- Same preferences-observation replacement as Site 1.
- postbox.transaction { transaction.getPeer / getPeerCachedData as?
CachedGroupData / CachedChannelData; FoundPeer(peer:subscribers:) }
-> context.engine.data.get(EngineDataMap(...TelegramEngine.Engine-
Data.Item.Peer.Peer.init(id:))) + pattern match on EnginePeer
.user / .secretChat / .legacyGroup / .channel
- Signal element: [(peer: FoundPeer, value: Int32)] -> [(peer: Engine-
Peer, value: Int32)]. FoundPeer wrapper and its `subscribers` field
dropped — computed but never read downstream (consumers only read
.isEmpty, .count, and .prefix(3).map { EnginePeer($0.peer.peer) }).
Consumer update:
peerExceptions.prefix(3).map { EnginePeer($0.peer.peer) } ->
.prefix(3).map { $0.peer }
Typealias fixup (caught by first-pass build failure):
var mergedMedia: [MessageId: Int64] -> [EngineMessage.Id: Int64]
(MessageId is raw Postbox; must use the EngineMessage.Id typealias
when import Postbox is removed.)
Reusable pattern documented in CLAUDE.md: TelegramEngine.EngineData.Item
.Configuration.ApplicationSpecificPreference(key: ValueBoxKey) is the
general-purpose engine replacement for the postbox.combinedView(keys:
[.preferences(keys: Set([key]))]) + PreferencesView idiom. Works from
any module importing TelegramCore (without import Postbox) because
passing PreferencesKeys.<name> keeps ValueBoxKey as an inferred-only
type that never gets named in the consumer.
Net: 1 file changed, +30 / -54.
StorageUsageScreen.swift is now Postbox-free. The wave 8 outcome's other
future candidate (StorageFileListPanelComponent.swift's Icon.media(Media,
...) enum case) remains — trivial future wave will land the whole-module
drop.
Plan: docs/superpowers/plans/2026-04-20-postbox-to-telegramengine-wave-9.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
635d392484
commit
1a432362a3
3 changed files with 218 additions and 55 deletions
25
CLAUDE.md
25
CLAUDE.md
|
|
@ -231,6 +231,31 @@ Single atomic commit. Build verified green (59s incremental build, 27 actions).
|
|||
|
||||
Plan / record: `docs/superpowers/plans/2026-04-20-postbox-to-telegramengine-wave-8.md`.
|
||||
|
||||
### Wave 9 outcome (2026-04-20)
|
||||
|
||||
Closes the first of the two "future-wave candidates" left open by wave 8: rewrites both `AccountSpecificCacheStorageSettings` preferences-view observation sites in `StorageUsageScreen.swift` using engine APIs, and drops `import Postbox` from that file.
|
||||
|
||||
**Site 1 — `cacheSettingsExceptionCount` signal** (former lines 1047–1087):
|
||||
- `postbox.combinedView(keys: [.preferences(keys: Set([PreferencesKeys.accountSpecificCacheStorageSettings]))])` + `PreferencesView` extraction →
|
||||
`context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: PreferencesKeys.accountSpecificCacheStorageSettings))` + `preferencesEntry?.get(AccountSpecificCacheStorageSettings.self) ?? .defaultSettings`.
|
||||
- Downstream `EngineDataMap` + `EnginePeer` per-category counting logic unchanged (already engine-only).
|
||||
|
||||
**Site 2 — `peerExceptions` signal in `openKeepMediaCategory`** (former lines 3131–3196):
|
||||
- Same preferences observation replacement as Site 1.
|
||||
- `postbox.transaction { transaction.getPeer / transaction.getPeerCachedData as? CachedGroupData / CachedChannelData; FoundPeer(peer:subscribers:) }` → `context.engine.data.get(EngineDataMap(...TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))` + pattern match on `EnginePeer.user / .secretChat / .legacyGroup / .channel`.
|
||||
- Signal element type `[(peer: FoundPeer, value: Int32)]` → `[(peer: EnginePeer, value: Int32)]`. `FoundPeer` wrapper and its `subscribers` field dropped entirely — they were computed by the transaction block but never read by downstream consumers (the only consumer sites read `.isEmpty`, `.count`, and `.prefix(3).map { EnginePeer($0.peer.peer) }`).
|
||||
- One downstream consumer updated: `peerExceptions.prefix(3).map { EnginePeer($0.peer.peer) }` → `.prefix(3).map { $0.peer }` at the `MultiplePeerAvatarsContextItem` construction (redundant wrap removed since `$0.peer` is already `EnginePeer`).
|
||||
|
||||
**Typealias fixup.** With `import Postbox` removed, `var mergedMedia: [MessageId: Int64]` at former line 2397 needed renaming to `[EngineMessage.Id: Int64]`. `MessageId` is the raw Postbox type name — CLAUDE.md's engine-typealias cheat sheet lists these as migration targets, not pre-existing aliases in TelegramCore. Caught by first-pass build failure (`cannot find type 'MessageId' in scope`).
|
||||
|
||||
**Reusable pattern.** `TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: ValueBoxKey)` (at `TelegramCore/Sources/TelegramEngine/Data/ConfigurationData.swift:356`) is the general-purpose engine replacement for any `postbox.combinedView(keys: [.preferences(keys: Set([key]))]) + PreferencesView` idiom — takes any `ValueBoxKey`, returns `PreferencesEntry?`, decodes via `.get(T.self)`. Crucially, callers need not `import Postbox` even though `ValueBoxKey` is a Postbox type: passing `PreferencesKeys.<name>` through makes `ValueBoxKey` an inferred-only type that never gets named in the consumer module. Use this pattern when de-Postboxing any future module that observes preferences.
|
||||
|
||||
`StorageUsageScreen.swift` is now Postbox-free. The wave 8 outcome's other candidate (`StorageFileListPanelComponent.swift`'s `Icon.media(Media, ...)` enum case) remains — trivial future wave to split into `.mediaFile(TelegramMediaFile, ...)` / `.mediaImage(TelegramMediaImage, ...)` cases, at which point the `StorageUsageScreen` consumer module as a whole becomes Postbox-free.
|
||||
|
||||
Net: 1 file changed, +30 / -54. Build verified green (27 actions, cached).
|
||||
|
||||
Plan / record: `docs/superpowers/plans/2026-04-20-postbox-to-telegramengine-wave-9.md`.
|
||||
|
||||
### Modules currently free of `import Postbox` (running tally)
|
||||
|
||||
Consumer modules that no longer import Postbox, across all waves and standalone commits:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,162 @@
|
|||
# Postbox → TelegramEngine Wave 9 Implementation Plan
|
||||
|
||||
> **For agentic workers:** This plan was executed in a single session; steps below are a post-hoc record of the work landed, not a to-do list.
|
||||
|
||||
**Goal:** Finish the `StorageUsageScreen` de-Postbox work started in wave 8 by rewriting the two remaining direct-postbox sites that observe `AccountSpecificCacheStorageSettings`, and drop `import Postbox` from `StorageUsageScreen.swift`.
|
||||
|
||||
**Architecture:** Replace `postbox.combinedView(keys: [.preferences(...)]) + PreferencesView` observation with `context.engine.data.subscribe(TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key:))`, which returns `PreferencesEntry?` and is then decoded the same way (`.get(AccountSpecificCacheStorageSettings.self)`). Replace the transaction-based per-peer classification (`transaction.getPeer` + `transaction.getPeerCachedData as? CachedGroupData/CachedChannelData`) with an `EngineDataMap` of `TelegramEngine.EngineData.Item.Peer.Peer.init(id:)` lookups producing `EnginePeer?` values that pattern-match on `.user` / `.legacyGroup` / `.channel(channel)` / `.secretChat`. The `FoundPeer(peer:subscribers:)` wrapper in the signal's element type is dropped entirely since downstream consumers (`peerExceptions.isEmpty`, `.count`, `.prefix(3).map { EnginePeer($0.peer.peer) }`) never read `subscribers`.
|
||||
|
||||
**Tech Stack:** Swift / Bazel. No unit tests.
|
||||
|
||||
**Build command:**
|
||||
|
||||
```bash
|
||||
source ~/.zshrc 2>/dev/null; PATH=/opt/homebrew/opt/ruby/bin:`gem environment gemdir`/bin:$PATH python3 build-system/Make/Make.py --overrideXcodeVersion --cacheDir ~/telegram-bazel-cache build --configurationPath build-system/appstore-configuration.json --gitCodesigningRepository git@gitlab.com:peter-iakovlev/fastlanematch.git --gitCodesigningType development --gitCodesigningUseCurrent --buildNumber 1 --configuration debug_sim_arm64 --continueOnError
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Scope
|
||||
|
||||
Two direct-postbox site clusters rewritten in `StorageUsageScreen.swift`:
|
||||
|
||||
1. **Site 1 (former lines 1047–1087)** — `cacheSettingsExceptionCount` signal. Preserved its downstream `EngineDataMap` + `EnginePeer` per-category counting logic unchanged; only the preferences observation replaced.
|
||||
2. **Site 2 (former lines 3131–3196)** — `peerExceptions` signal inside `openKeepMediaCategory`. Both the preferences observation AND the `postbox.transaction { transaction.getPeer / transaction.getPeerCachedData ... FoundPeer(...) }` block replaced. Signal element type changed from `[(peer: FoundPeer, value: Int32)]` to `[(peer: EnginePeer, value: Int32)]`; `FoundPeer` and the unread `subscribers` field dropped.
|
||||
|
||||
One consumer-side edit: `peerExceptions.prefix(3).map { EnginePeer($0.peer.peer) }` → `peerExceptions.prefix(3).map { $0.peer }` (at the `MultiplePeerAvatarsContextItem` construction).
|
||||
|
||||
One typealias fixup: `var mergedMedia: [MessageId: Int64]` → `[EngineMessage.Id: Int64]` (required once `import Postbox` is removed, since `MessageId` is the raw Postbox name, not a TelegramCore typealias).
|
||||
|
||||
`import Postbox` removed from `StorageUsageScreen.swift`.
|
||||
|
||||
---
|
||||
|
||||
## Tasks
|
||||
|
||||
### Task 1: Rewrite site 1 — cacheSettingsExceptionCount
|
||||
|
||||
**Files:**
|
||||
- Modify: `submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift` (former 1047–1058).
|
||||
|
||||
Replace the preferences observation header. The downstream `mapToSignal { ... EngineDataMap ... EnginePeer ... }` body is already Engine-only and unchanged.
|
||||
|
||||
Before:
|
||||
|
||||
```swift
|
||||
let viewKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.accountSpecificCacheStorageSettings]))
|
||||
let cacheSettingsExceptionCount: Signal<[CacheStorageSettings.PeerStorageCategory: Int32], NoError> = component.context.account.postbox.combinedView(keys: [viewKey])
|
||||
|> map { views -> AccountSpecificCacheStorageSettings in
|
||||
let cacheSettings: AccountSpecificCacheStorageSettings
|
||||
if let view = views.views[viewKey] as? PreferencesView, let value = view.values[PreferencesKeys.accountSpecificCacheStorageSettings]?.get(AccountSpecificCacheStorageSettings.self) {
|
||||
cacheSettings = value
|
||||
} else {
|
||||
cacheSettings = AccountSpecificCacheStorageSettings.defaultSettings
|
||||
}
|
||||
return cacheSettings
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|> mapToSignal { ... }
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```swift
|
||||
let cacheSettingsExceptionCount: Signal<[CacheStorageSettings.PeerStorageCategory: Int32], NoError> = context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: PreferencesKeys.accountSpecificCacheStorageSettings)
|
||||
)
|
||||
|> map { preferencesEntry -> AccountSpecificCacheStorageSettings in
|
||||
return preferencesEntry?.get(AccountSpecificCacheStorageSettings.self) ?? AccountSpecificCacheStorageSettings.defaultSettings
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|> mapToSignal { ... }
|
||||
```
|
||||
|
||||
### Task 2: Rewrite site 2 — peerExceptions
|
||||
|
||||
**Files:**
|
||||
- Modify: `submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift` (former 3131–3196).
|
||||
|
||||
Replace both the preferences observation (as in Task 1) AND the subsequent `mapToSignal { context.account.postbox.transaction { ... } }` block. Signal element type changes from `[(peer: FoundPeer, value: Int32)]` to `[(peer: EnginePeer, value: Int32)]`. `subscriberCount` is not preserved — it's computed but never read by downstream consumers.
|
||||
|
||||
After (showing the `peerExceptions` signal in full):
|
||||
|
||||
```swift
|
||||
let peerExceptions: Signal<[(peer: EnginePeer, value: Int32)], NoError> = accountSpecificSettings
|
||||
|> mapToSignal { accountSpecificSettings -> Signal<[(peer: EnginePeer, value: Int32)], NoError> in
|
||||
return context.engine.data.get(
|
||||
EngineDataMap(accountSpecificSettings.peerStorageTimeoutExceptions.map(\.key).map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))
|
||||
)
|
||||
|> map { peers -> [(peer: EnginePeer, value: Int32)] in
|
||||
var result: [(peer: EnginePeer, value: Int32)] = []
|
||||
for item in accountSpecificSettings.peerStorageTimeoutExceptions {
|
||||
guard let peer = peers[item.key] ?? nil else { continue }
|
||||
let peerCategory: CacheStorageSettings.PeerStorageCategory
|
||||
switch peer {
|
||||
case .user, .secretChat:
|
||||
peerCategory = .privateChats
|
||||
case .legacyGroup:
|
||||
peerCategory = .groups
|
||||
case let .channel(channel):
|
||||
if case .group = channel.info {
|
||||
peerCategory = .groups
|
||||
} else {
|
||||
peerCategory = .channels
|
||||
}
|
||||
}
|
||||
if peerCategory != mappedCategory { continue }
|
||||
result.append((peer: peer, value: item.value))
|
||||
}
|
||||
return result.sorted(by: { lhs, rhs in
|
||||
if lhs.value != rhs.value {
|
||||
return lhs.value < rhs.value
|
||||
}
|
||||
return lhs.peer.debugDisplayTitle < rhs.peer.debugDisplayTitle
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Task 3: Update consumer of `peerExceptions`
|
||||
|
||||
**Files:**
|
||||
- Modify: `submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift` (former 3288).
|
||||
|
||||
`peerExceptions.prefix(3).map { EnginePeer($0.peer.peer) }` → `peerExceptions.prefix(3).map { $0.peer }`. The `MultiplePeerAvatarsContextItem(context:, peers: [EnginePeer], totalCount:, action:)` signature is unchanged — we simply drop the redundant `EnginePeer(...)` wrap because `$0.peer` is now already an `EnginePeer`.
|
||||
|
||||
### Task 4: Drop `import Postbox`
|
||||
|
||||
**Files:**
|
||||
- Modify: `submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift` (line 12).
|
||||
|
||||
Remove the `import Postbox` line.
|
||||
|
||||
### Task 5: Typealias fixup for `MessageId`
|
||||
|
||||
**Files:**
|
||||
- Modify: `submodules/TelegramUI/Components/StorageUsageScreen/Sources/StorageUsageScreen.swift` (former 2397).
|
||||
|
||||
`var mergedMedia: [MessageId: Int64]` → `[EngineMessage.Id: Int64]`. `MessageId` is the raw Postbox type name; with `import Postbox` removed, the type must be named through the `EngineMessage.Id` typealias. Discovered by first-pass build failure `cannot find type 'MessageId' in scope`.
|
||||
|
||||
### Task 6: Full project build
|
||||
|
||||
Expected green. Incremental build: ~60s (cached), 27 actions.
|
||||
|
||||
### Task 7: Commit
|
||||
|
||||
Single wave-9 atomic commit. CLAUDE.md updates the wave 8 outcome's "future-wave candidates" note since this wave closes both of them. `StorageUsageScreen` (the module as a whole) now has `StorageUsageScreen.swift` Postbox-free; the module's `StorageFileListPanelComponent.swift` still imports Postbox because of the `Icon.media(Media, TelegramMediaImageRepresentation)` enum case (trivial future wave, as previously noted).
|
||||
|
||||
---
|
||||
|
||||
## Outcome (2026-04-20)
|
||||
|
||||
Single atomic commit. Build verified green (27 actions, ~60s incremental).
|
||||
|
||||
Net change: 1 file, +30 / -54 lines (-24 simplification).
|
||||
|
||||
Lessons:
|
||||
|
||||
- **`ApplicationSpecificPreference(key:)` is the general-purpose engine replacement** for any `postbox.combinedView(keys: [.preferences(keys: Set([key]))])` idiom. Takes a `ValueBoxKey`, returns `PreferencesEntry?`, decodes via `.get(T.self)`. Usable from any module that imports `TelegramCore` even without `import Postbox`, because the `ValueBoxKey`-typed input is obtained through a statically-named `PreferencesKeys.*` member (no `ValueBoxKey` identifier appears in the consumer).
|
||||
- **`MessageId` is raw Postbox, not a TelegramCore typealias.** CLAUDE.md's "engine typealias cheat sheet" labels `PeerId`, `MessageId`, etc. as migration *targets*, not existing aliases. Files that drop `import Postbox` must rename these to `EngineMessage.Id` / `EnginePeer.Id`. Caught by the first-pass build failure.
|
||||
- **Dead-code detection during rewrites.** The transaction block's `subscriberCount` computation and the `FoundPeer.subscribers` field it populated were never consumed downstream. The rewrite simply dropped them, shrinking the code further than a 1:1 rewrite would have.
|
||||
|
||||
`StorageUsageScreen.swift` is now Postbox-free. The `StorageUsageScreen` consumer module as a whole is still not fully Postbox-free because `StorageFileListPanelComponent.swift` retains `import Postbox` for its `Icon.media(Media, TelegramMediaImageRepresentation)` enum case (3 construction sites; trivial future wave splits into `.mediaFile(TelegramMediaFile, ...)` / `.mediaImage(TelegramMediaImage, ...)`).
|
||||
|
|
@ -9,7 +9,6 @@ import ComponentDisplayAdapters
|
|||
import TelegramPresentationData
|
||||
import AccountContext
|
||||
import TelegramCore
|
||||
import Postbox
|
||||
import MultilineTextComponent
|
||||
import EmojiStatusComponent
|
||||
import Markdown
|
||||
|
|
@ -1044,17 +1043,11 @@ final class StorageUsageScreenComponent: Component {
|
|||
|
||||
if self.statsDisposable == nil {
|
||||
let context = component.context
|
||||
let viewKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.accountSpecificCacheStorageSettings]))
|
||||
let cacheSettingsExceptionCount: Signal<[CacheStorageSettings.PeerStorageCategory: Int32], NoError> = component.context.account.postbox.combinedView(keys: [viewKey])
|
||||
|> map { views -> AccountSpecificCacheStorageSettings in
|
||||
let cacheSettings: AccountSpecificCacheStorageSettings
|
||||
if let view = views.views[viewKey] as? PreferencesView, let value = view.values[PreferencesKeys.accountSpecificCacheStorageSettings]?.get(AccountSpecificCacheStorageSettings.self) {
|
||||
cacheSettings = value
|
||||
} else {
|
||||
cacheSettings = AccountSpecificCacheStorageSettings.defaultSettings
|
||||
}
|
||||
|
||||
return cacheSettings
|
||||
let cacheSettingsExceptionCount: Signal<[CacheStorageSettings.PeerStorageCategory: Int32], NoError> = context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: PreferencesKeys.accountSpecificCacheStorageSettings)
|
||||
)
|
||||
|> map { preferencesEntry -> AccountSpecificCacheStorageSettings in
|
||||
return preferencesEntry?.get(AccountSpecificCacheStorageSettings.self) ?? AccountSpecificCacheStorageSettings.defaultSettings
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|> mapToSignal { accountSpecificSettings -> Signal<[CacheStorageSettings.PeerStorageCategory: Int32], NoError> in
|
||||
|
|
@ -2401,7 +2394,7 @@ final class StorageUsageScreenComponent: Component {
|
|||
|
||||
result.messages = messages
|
||||
|
||||
var mergedMedia: [MessageId: Int64] = [:]
|
||||
var mergedMedia: [EngineMessage.Id: Int64] = [:]
|
||||
if let categoryStats = contextStats.categories[.photos] {
|
||||
mergedMedia = categoryStats.messages
|
||||
}
|
||||
|
|
@ -3128,69 +3121,52 @@ final class StorageUsageScreenComponent: Component {
|
|||
self.controller?()?.presentInGlobalOverlay(c, with: nil)
|
||||
}
|
||||
|
||||
let viewKey: PostboxViewKey = .preferences(keys: Set([PreferencesKeys.accountSpecificCacheStorageSettings]))
|
||||
let accountSpecificSettings: Signal<AccountSpecificCacheStorageSettings, NoError> = context.account.postbox.combinedView(keys: [viewKey])
|
||||
|> map { views -> AccountSpecificCacheStorageSettings in
|
||||
let cacheSettings: AccountSpecificCacheStorageSettings
|
||||
if let view = views.views[viewKey] as? PreferencesView, let value = view.values[PreferencesKeys.accountSpecificCacheStorageSettings]?.get(AccountSpecificCacheStorageSettings.self) {
|
||||
cacheSettings = value
|
||||
} else {
|
||||
cacheSettings = AccountSpecificCacheStorageSettings.defaultSettings
|
||||
}
|
||||
|
||||
return cacheSettings
|
||||
let accountSpecificSettings: Signal<AccountSpecificCacheStorageSettings, NoError> = context.engine.data.subscribe(
|
||||
TelegramEngine.EngineData.Item.Configuration.ApplicationSpecificPreference(key: PreferencesKeys.accountSpecificCacheStorageSettings)
|
||||
)
|
||||
|> map { preferencesEntry -> AccountSpecificCacheStorageSettings in
|
||||
return preferencesEntry?.get(AccountSpecificCacheStorageSettings.self) ?? AccountSpecificCacheStorageSettings.defaultSettings
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
let peerExceptions: Signal<[(peer: FoundPeer, value: Int32)], NoError> = accountSpecificSettings
|
||||
|> mapToSignal { accountSpecificSettings -> Signal<[(peer: FoundPeer, value: Int32)], NoError> in
|
||||
return context.account.postbox.transaction { transaction -> [(peer: FoundPeer, value: Int32)] in
|
||||
var result: [(peer: FoundPeer, value: Int32)] = []
|
||||
|
||||
|
||||
let peerExceptions: Signal<[(peer: EnginePeer, value: Int32)], NoError> = accountSpecificSettings
|
||||
|> mapToSignal { accountSpecificSettings -> Signal<[(peer: EnginePeer, value: Int32)], NoError> in
|
||||
return context.engine.data.get(
|
||||
EngineDataMap(accountSpecificSettings.peerStorageTimeoutExceptions.map(\.key).map(TelegramEngine.EngineData.Item.Peer.Peer.init(id:)))
|
||||
)
|
||||
|> map { peers -> [(peer: EnginePeer, value: Int32)] in
|
||||
var result: [(peer: EnginePeer, value: Int32)] = []
|
||||
|
||||
for item in accountSpecificSettings.peerStorageTimeoutExceptions {
|
||||
let peerId = item.key
|
||||
let value = item.value
|
||||
|
||||
guard let peer = transaction.getPeer(peerId) else {
|
||||
guard let peer = peers[item.key] ?? nil else {
|
||||
continue
|
||||
}
|
||||
let peerCategory: CacheStorageSettings.PeerStorageCategory
|
||||
var subscriberCount: Int32?
|
||||
if peer is TelegramUser {
|
||||
switch peer {
|
||||
case .user, .secretChat:
|
||||
peerCategory = .privateChats
|
||||
} else if peer is TelegramGroup {
|
||||
case .legacyGroup:
|
||||
peerCategory = .groups
|
||||
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedGroupData {
|
||||
subscriberCount = (cachedData.participants?.participants.count).flatMap(Int32.init)
|
||||
}
|
||||
} else if let channel = peer as? TelegramChannel {
|
||||
case let .channel(channel):
|
||||
if case .group = channel.info {
|
||||
peerCategory = .groups
|
||||
} else {
|
||||
peerCategory = .channels
|
||||
}
|
||||
if peerCategory == mappedCategory {
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData {
|
||||
subscriberCount = cachedData.participantsSummary.memberCount
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
if peerCategory != mappedCategory {
|
||||
continue
|
||||
}
|
||||
|
||||
result.append((peer: FoundPeer(peer: peer, subscribers: subscriberCount), value: value))
|
||||
|
||||
result.append((peer: peer, value: item.value))
|
||||
}
|
||||
|
||||
|
||||
return result.sorted(by: { lhs, rhs in
|
||||
if lhs.value != rhs.value {
|
||||
return lhs.value < rhs.value
|
||||
}
|
||||
return lhs.peer.peer.debugDisplayTitle < rhs.peer.peer.debugDisplayTitle
|
||||
return lhs.peer.debugDisplayTitle < rhs.peer.debugDisplayTitle
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -3285,7 +3261,7 @@ final class StorageUsageScreenComponent: Component {
|
|||
}
|
||||
})))
|
||||
} else {
|
||||
subItems.append(.custom(MultiplePeerAvatarsContextItem(context: context, peers: peerExceptions.prefix(3).map { EnginePeer($0.peer.peer) }, totalCount: peerExceptions.count, action: { c, _ in
|
||||
subItems.append(.custom(MultiplePeerAvatarsContextItem(context: context, peers: peerExceptions.prefix(3).map { $0.peer }, totalCount: peerExceptions.count, action: { c, _ in
|
||||
c.dismiss(completion: {
|
||||
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue