mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-05 19:28:46 +02:00
Postbox -> TelegramEngine wave 15: SelectablePeerNode stateManager collapse
Applies the wave-11/12 AccountStateManager collapse pattern to SelectablePeerNode. Module is now fully Postbox-free (source + BUILD). - SelectablePeerNode.setup(... postbox: Postbox, network: Network, ...) -> setup(... stateManager: AccountStateManager, ...). Same for setupStoryRepost. AvatarNode.setPeer and EmojiStatusComponent are forwarded as stateManager.postbox / .network without naming Postbox. - Three Namespaces.Peer.SecretChat == checks rewritten to use the existing PeerId.isSecretChat extension (as in wave 13). - ShareControllerPeerGridItem.setup / setupStoryRepost and HorizontalPeerItem.setup call sites collapse to stateManager:. JoinLinkPreviewPeerContentNode uses the convenience setup(context: AccountContext) and is unchanged. - Drop import Postbox in SelectablePeerNode.swift and the //submodules/Postbox:Postbox dep in SelectablePeerNode/BUILD. The stateManager fallback (over the normally-preferred engine: TelegramEngine) is used because SelectablePeerNode crosses the Share Extension boundary: ShareControllerAccountContextExtension has no Account, so TelegramEngine(account:) is physically unreachable there. This matches the "rare but genuine fallback" clause of feedback_postbox_refactor_handle.md. Build verified green (debug_sim_arm64, 193 actions). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b20cd3502b
commit
46566e7155
5 changed files with 38 additions and 17 deletions
26
CLAUDE.md
26
CLAUDE.md
|
|
@ -358,6 +358,31 @@ Net (wave 14 alone): 98 files changed, 0 insertions / 98 deletions.
|
|||
|
||||
Plan / record: (no plan doc this wave — mechanical sweep).
|
||||
|
||||
### Wave 15 outcome (2026-04-20)
|
||||
|
||||
Applies the wave-11/12 `stateManager: AccountStateManager` collapse pattern to `SelectablePeerNode` — another wave-1-era candidate listed in the post-wave-14 shortlist. Module becomes fully Postbox-free (source + BUILD).
|
||||
|
||||
**`SelectablePeerNode` fully Postbox-free.** Two public setup methods migrated:
|
||||
- `setup(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network, …)` → `setup(accountPeerId:, stateManager: AccountStateManager, …)`.
|
||||
- `setupStoryRepost(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network, …)` → `setupStoryRepost(accountPeerId:, stateManager: AccountStateManager, …)`.
|
||||
|
||||
Internal forwards rewired: `AvatarNode.setPeer(…, postbox: stateManager.postbox, network: stateManager.network, …)` and `EmojiStatusComponent(postbox: stateManager.postbox, …)`. Neither site names `Postbox` in the consumer — Swift infers through transitive module visibility.
|
||||
|
||||
**Namespaces.Peer.SecretChat fixup (×3).** Replaced `peer.peerId.namespace == Namespaces.Peer.SecretChat` checks with `peer.peerId.isSecretChat` at three sites, matching the wave-13 pattern (`PeerId.isSecretChat` at `TelegramCore/Sources/Utils/PeerUtils.swift:611`). The third site (`updateSelection` in the not-selected branch) additionally needed an `?? false` fallback — previous expression was `self.peer?.peerId.namespace == Namespaces.Peer.SecretChat` (optional-equals-non-optional produces `Bool`), new expression is `(self.peer?.peerId.isSecretChat ?? false)`.
|
||||
|
||||
**Share-Extension boundary — `stateManager:` over `engine:`.** `SelectablePeerNode` is used by `ShareControllerPeerGridItem`, whose context is `ShareControllerAccountContext`. That protocol exposes `stateManager: AccountStateManager` and `engineData: TelegramEngine.EngineData`, but **no `engine: TelegramEngine`** — and the Share Extension's `ShareControllerAccountContextExtension` concrete impl has no `Account`, so constructing a full `TelegramEngine` (`init(account: Account)`) is physically unreachable there. This is the documented "rare but genuine" fallback to `stateManager:` from the user-preference memory (`feedback_postbox_refactor_handle.md`) — prefer `engine:` except when crossing the Share-Extension boundary.
|
||||
|
||||
**Three external call sites migrated:**
|
||||
- `HorizontalPeerItem/Sources/HorizontalPeerItem.swift:227` (wave 12's `stateManager:` field now forwards directly): `postbox: item.stateManager.postbox, network: item.stateManager.network` → `stateManager: item.stateManager`.
|
||||
- `ShareController/Sources/ShareControllerPeerGridItem.swift:237` (setup): `postbox: context.stateManager.postbox, network: context.stateManager.network` → `stateManager: context.stateManager`.
|
||||
- `ShareController/Sources/ShareControllerPeerGridItem.swift:273` (setupStoryRepost): same.
|
||||
|
||||
**Convenience init unchanged.** `setup(context: AccountContext, …)` now delegates with `stateManager: context.account.stateManager`; signature unchanged — `JoinLinkPreviewPeerContentNode.swift:147` (the one caller using the convenience init) needed no edit.
|
||||
|
||||
Net: 4 files changed, +12 / -17 lines. Build verified green (193 actions, 131s — Telegram.ipa target built successfully).
|
||||
|
||||
Plan / record: (no plan doc this wave — pattern-application, low-complexity).
|
||||
|
||||
### Modules currently free of `import Postbox` (running tally)
|
||||
|
||||
Consumer modules that no longer import Postbox, across all waves and standalone commits:
|
||||
|
|
@ -376,6 +401,7 @@ Consumer modules that no longer import Postbox, across all waves and standalone
|
|||
- `StorageUsageScreen` (waves 8–10)
|
||||
- `ActionSheetPeerItem` (wave 11; revisits wave-1 abandonment)
|
||||
- `HorizontalPeerItem` (wave 12; applies wave-11 pattern)
|
||||
- `SelectablePeerNode` (wave 15; applies wave-11 pattern; ShareExtension-boundary stateManager fallback)
|
||||
- `AttachmentTextInputPanelNode` BUILD cleanup (wave 13; source was already clean from wave 6)
|
||||
- **Wave 14 BUILD-dep sweep: 98 modules' BUILDs cleaned** — same modules as the wave-6 batch; this sweep fixed their leftover `//submodules/Postbox:Postbox` BUILD deps. Candidate list in `/tmp/postbox-dep-candidates.txt` at commit time; derivable by the script in "Wave 14 outcome".
|
||||
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ public final class HorizontalPeerItemNode: ListViewItemNode {
|
|||
} else {
|
||||
strongSelf.peerNode.compact = false
|
||||
}
|
||||
strongSelf.peerNode.setup(accountPeerId: item.accountPeerId, postbox: item.stateManager.postbox, network: item.stateManager.network, energyUsageSettings: item.energyUsageSettings, contentSettings: item.contentSettings, animationCache: item.animationCache, animationRenderer: item.animationRenderer, resolveInlineStickers: item.resolveInlineStickers, theme: item.theme, strings: item.strings, peer: EngineRenderedPeer(peer: item.peer), requiresPremiumForMessaging: false, numberOfLines: 1, synchronousLoad: synchronousLoads)
|
||||
strongSelf.peerNode.setup(accountPeerId: item.accountPeerId, stateManager: item.stateManager, energyUsageSettings: item.energyUsageSettings, contentSettings: item.contentSettings, animationCache: item.animationCache, animationRenderer: item.animationRenderer, resolveInlineStickers: item.resolveInlineStickers, theme: item.theme, strings: item.strings, peer: EngineRenderedPeer(peer: item.peer), requiresPremiumForMessaging: false, numberOfLines: 1, synchronousLoad: synchronousLoads)
|
||||
strongSelf.peerNode.frame = CGRect(origin: CGPoint(), size: itemLayout.size)
|
||||
strongSelf.peerNode.updateSelection(selected: item.isPeerSelected(item.peer.id), animated: false)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ swift_library(
|
|||
deps = [
|
||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||
"//submodules/TelegramCore:TelegramCore",
|
||||
"//submodules/Postbox:Postbox",
|
||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||
"//submodules/Display:Display",
|
||||
"//submodules/TelegramPresentationData:TelegramPresentationData",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import UIKit
|
|||
import AsyncDisplayKit
|
||||
import Display
|
||||
import TelegramCore
|
||||
import Postbox
|
||||
import SwiftSignalKit
|
||||
import TelegramPresentationData
|
||||
import AvatarNode
|
||||
|
|
@ -108,7 +107,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||
didSet {
|
||||
if !self.theme.isEqual(to: oldValue) {
|
||||
if let peer = self.peer, let mainPeer = peer.chatMainPeer {
|
||||
self.textNode.attributedText = NSAttributedString(string: mainPeer.debugDisplayTitle, font: textFont, textColor: self.currentSelected ? self.theme.selectedTextColor : (peer.peerId.namespace == Namespaces.Peer.SecretChat ? self.theme.secretTextColor : self.theme.textColor), paragraphAlignment: .center)
|
||||
self.textNode.attributedText = NSAttributedString(string: mainPeer.debugDisplayTitle, font: textFont, textColor: self.currentSelected ? self.theme.selectedTextColor : (peer.peerId.isSecretChat ? self.theme.secretTextColor : self.theme.textColor), paragraphAlignment: .center)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -159,8 +158,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||
public func setup(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool, requiresStars: Int64? = nil, customTitle: String? = nil, iconId: Int64? = nil, iconColor: Int32? = nil, online: Bool = false, numberOfLines: Int = 2, synchronousLoad: Bool) {
|
||||
self.setup(
|
||||
accountPeerId: context.account.peerId,
|
||||
postbox: context.account.postbox,
|
||||
network: context.account.network,
|
||||
stateManager: context.account.stateManager,
|
||||
energyUsageSettings: context.sharedContext.energyUsageSettings,
|
||||
contentSettings: context.currentContentSettings.with { $0 },
|
||||
animationCache: context.animationCache,
|
||||
|
|
@ -182,7 +180,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||
)
|
||||
}
|
||||
|
||||
public func setupStoryRepost(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network, theme: PresentationTheme, strings: PresentationStrings, synchronousLoad: Bool, storyMode: StoryMode) {
|
||||
public func setupStoryRepost(accountPeerId: EnginePeer.Id, stateManager: AccountStateManager, theme: PresentationTheme, strings: PresentationStrings, synchronousLoad: Bool, storyMode: StoryMode) {
|
||||
self.peer = nil
|
||||
|
||||
let title: String
|
||||
|
|
@ -202,14 +200,14 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||
|
||||
self.textNode.maximumNumberOfLines = 2
|
||||
self.textNode.attributedText = NSAttributedString(string: title, font: textFont, textColor: self.theme.textColor, paragraphAlignment: .center)
|
||||
self.avatarNode.setPeer(accountPeerId: accountPeerId, postbox: postbox, network: network, contentSettings: ContentSettings.default, theme: theme, peer: nil, overrideImage: overrideImage, emptyColor: self.theme.avatarPlaceholderColor, clipStyle: .round, synchronousLoad: synchronousLoad)
|
||||
self.avatarNode.setPeer(accountPeerId: accountPeerId, postbox: stateManager.postbox, network: stateManager.network, contentSettings: ContentSettings.default, theme: theme, peer: nil, overrideImage: overrideImage, emptyColor: self.theme.avatarPlaceholderColor, clipStyle: .round, synchronousLoad: synchronousLoad)
|
||||
|
||||
if case .repostIcon = overrideImage {
|
||||
self.avatarNode.playRepostAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
public func setup(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network, energyUsageSettings: EnergyUsageSettings, contentSettings: ContentSettings, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, resolveInlineStickers: @escaping ([Int64]) -> Signal<[Int64: TelegramMediaFile], NoError>, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool, requiresStars: Int64? = nil, customTitle: String? = nil, iconId: Int64? = nil, iconColor: Int32? = nil, online: Bool = false, numberOfLines: Int = 2, synchronousLoad: Bool) {
|
||||
public func setup(accountPeerId: EnginePeer.Id, stateManager: AccountStateManager, energyUsageSettings: EnergyUsageSettings, contentSettings: ContentSettings, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, resolveInlineStickers: @escaping ([Int64]) -> Signal<[Int64: TelegramMediaFile], NoError>, theme: PresentationTheme, strings: PresentationStrings, peer: EngineRenderedPeer, requiresPremiumForMessaging: Bool, requiresStars: Int64? = nil, customTitle: String? = nil, iconId: Int64? = nil, iconColor: Int32? = nil, online: Bool = false, numberOfLines: Int = 2, synchronousLoad: Bool) {
|
||||
let isFirstTime = self.peer == nil
|
||||
self.peer = peer
|
||||
guard let mainPeer = peer.chatOrMonoforumMainPeer else {
|
||||
|
|
@ -222,7 +220,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||
if requiresPremiumForMessaging {
|
||||
defaultColor = self.theme.textColor.withMultipliedAlpha(0.4)
|
||||
} else {
|
||||
defaultColor = peer.peerId.namespace == Namespaces.Peer.SecretChat ? self.theme.secretTextColor : self.theme.textColor
|
||||
defaultColor = peer.peerId.isSecretChat ? self.theme.secretTextColor : self.theme.textColor
|
||||
}
|
||||
|
||||
var isForum = false
|
||||
|
|
@ -256,7 +254,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||
} else {
|
||||
clipStyle = .round
|
||||
}
|
||||
self.avatarNode.setPeer(accountPeerId: accountPeerId, postbox: postbox, network: network, contentSettings: contentSettings, theme: theme, peer: mainPeer, overrideImage: overrideImage, emptyColor: self.theme.avatarPlaceholderColor, clipStyle: clipStyle, synchronousLoad: synchronousLoad)
|
||||
self.avatarNode.setPeer(accountPeerId: accountPeerId, postbox: stateManager.postbox, network: stateManager.network, contentSettings: contentSettings, theme: theme, peer: mainPeer, overrideImage: overrideImage, emptyColor: self.theme.avatarPlaceholderColor, clipStyle: clipStyle, synchronousLoad: synchronousLoad)
|
||||
|
||||
if let requiresStars {
|
||||
let avatarBadgeOutline: UIImageView
|
||||
|
|
@ -373,7 +371,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||
let iconSize = self.iconView.update(
|
||||
transition: .easeInOut(duration: 0.2),
|
||||
component: AnyComponent(EmojiStatusComponent(
|
||||
postbox: postbox,
|
||||
postbox: stateManager.postbox,
|
||||
energyUsageSettings: energyUsageSettings,
|
||||
resolveInlineStickers: resolveInlineStickers,
|
||||
animationCache: animationCache,
|
||||
|
|
@ -404,7 +402,7 @@ public final class SelectablePeerNode: ASDisplayNode {
|
|||
self.currentSelected = selected
|
||||
|
||||
if let attributedText = self.textNode.attributedText {
|
||||
self.textNode.attributedText = NSAttributedString(string: attributedText.string, font: textFont, textColor: selected ? self.theme.selectedTextColor : (self.peer?.peerId.namespace == Namespaces.Peer.SecretChat ? self.theme.secretTextColor : self.theme.textColor), paragraphAlignment: .center)
|
||||
self.textNode.attributedText = NSAttributedString(string: attributedText.string, font: textFont, textColor: selected ? self.theme.selectedTextColor : ((self.peer?.peerId.isSecretChat ?? false) ? self.theme.secretTextColor : self.theme.textColor), paragraphAlignment: .center)
|
||||
}
|
||||
|
||||
var isForum = false
|
||||
|
|
|
|||
|
|
@ -236,8 +236,7 @@ final class ShareControllerPeerGridItemNode: GridItemNode {
|
|||
let resolveInlineStickers = context.resolveInlineStickers
|
||||
self.peerNode.setup(
|
||||
accountPeerId: context.accountPeerId,
|
||||
postbox: context.stateManager.postbox,
|
||||
network: context.stateManager.network,
|
||||
stateManager: context.stateManager,
|
||||
energyUsageSettings: environment.energyUsageSettings,
|
||||
contentSettings: context.contentSettings,
|
||||
animationCache: context.animationCache,
|
||||
|
|
@ -272,8 +271,7 @@ final class ShareControllerPeerGridItemNode: GridItemNode {
|
|||
}
|
||||
self.peerNode.setupStoryRepost(
|
||||
accountPeerId: context.accountPeerId,
|
||||
postbox: context.stateManager.postbox,
|
||||
network: context.stateManager.network,
|
||||
stateManager: context.stateManager,
|
||||
theme: theme,
|
||||
strings: strings,
|
||||
synchronousLoad: synchronousLoad,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue