WinterGram/docs/superpowers/plans/2026-04-25-phn-peer-stored-field-engine-peer.md
isaac d1aa0db537 Postbox -> TelegramEngine waves 46-93 (squashed)
Squash of 63 commits spanning waves 46-93 (plus interspersed docs commits)
of the gradual Postbox->TelegramEngine consumer-side migration.

Scope: 139 files changed, 2123 insertions(+), 452 deletions(-).

## Themes by wave-block

**Waves 46-58 — Peer field migrations + facade additions**
Foundational EnginePeer convenience init additions (PeerReference, RenderedPeer,
SelectivePrivacyPeer). Multiple `peer: Peer` field migrations across PeerInfo,
ChatList, and SettingsUI components.

**Waves 59-73 — peer field cascade + EnginePeer wrap drops**
Series of single- to two-file peer-field migrations; consumer-side wrap
removal (`EnginePeer(peer)` -> direct EnginePeer use); `as? TelegramUser`
cast conversion to `case let .user(...)` enum match. Wave 64: RenderedPeer
convenience init. Wave 68: SelectivePrivacyPeer convenience init.

**Waves 74-83 — controller-Node bridge cleanup + small migrations**
Wave-71 shadow-pattern cleanup at controller->Node bridges. Migrations of
ChatRecentActionsController.peer (74), PeerInfoMember (75), MentionChatInputPanelItem
(76), PassportUI SecureIdAuthController (77), AccountWithInfo + ShareController
(78), peerInputActivitiesPromise (79), InactiveChannel (80), BlockedPeers (81),
openHashtag resolveSignal (82), NotificationExceptionsList (83).

**Waves 84-90 — TelegramEngine.Resources facade migrations**
Per-method Shape-A/B sweeps converting `<ctx>.account.postbox.mediaBox.X(...)`
to `<ctx>.engine.resources.X(...)`. Wave 90 was a single-commit big sweep:
40 fetchedMediaResource sites in 25 files migrated to engine.resources.fetch
facade in one atomic pass with first-pass-clean build.

Methods covered: storeResourceData, completedResourcePath, cancelInteractiveResourceFetch,
resourceRangesStatus, resourceStatus, fetch (fetchedMediaResource).

**Waves 91-92 — additional type migrations**
Wave 91: ItemListWebsiteItem.peer + RecentSessionsController enum-case payload
+ openWebSession callback Peer? -> EnginePeer?.
Wave 92: ChatListController StateHolder.EntryContext status type
MediaResourceStatus -> EngineMediaResource.FetchStatus.

**Wave 93 — speculative `import Postbox` drop sweep**
Drop import from 7 wave-touched files where it became unused; restore in 5
files where bare PeerId/Message/MediaId/StoryId references escaped the
pre-flight regex. Includes one MediaId(...) -> EngineMedia.Id(...) swap in
InAppPurchaseManager to unlock its import drop.

## Build state

Final state at squash: clean Telegram/Telegram build at debug_sim_arm64.

## Persistent-state notes

- Pre-existing WIP unchanged across the squashed range:
  - build-system/bazel-rules/sourcekit-bazel-bsp submodule marker
  - Untracked: build-system/tulsi/, submodules/TgVoip/, third-party/libx264/

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:48:15 +04:00

3 KiB
Raw Blame History

Wave 47 — PeerInfoHeaderNode.peer stored field Peer? → EnginePeer?

Date: 2026-04-25 Predecessor: Wave 46 (commit 5ca99da5a7) — PeerInfo avatar chain. Shape: Single-file stored-field type migration. No external API change (field is private).

Target

submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoHeaderNode.swift, stored field private var peer: Peer? at line 92.

Pre-flight inventory

grep -n "self\.peer\b" PeerInfoHeaderNode.swift returns exactly 3 references:

Line Code Site type Action
426 if let peer = self.peer, peer.profileImageRepresentations.isEmpty && gallery { Read None — profileImageRepresentations is forwarded by EnginePeer (see submodules/TelegramCore/Sources/TelegramEngine/Peers/Peer.swift:485). Compiles unchanged.
521 self.peer = peer?._asPeer() Assignment Drop the bridge → self.peer = peer. The peer parameter is already EnginePeer? after wave 45.
20492054 guard let self, let peer = self.peer, ... followed by peer: EnginePeer(peer), Read Drop the wrap at line 2054 → peer: peer,.

External access check: grep -rn "headerNode\.peer\b" submodules/ Telegram/ returns empty. The field is private; only same-file siblings touch it.

EnginePeer forwarding (re-confirmed at plan time):

  • profileImageRepresentations — forwarded (Peer.swift:485). ✓
  • EnginePeer(peer) (PHN:2054) — accepts EnginePeer directly when the local is already EnginePeer; drop the constructor.

Field-declaration change is the only "type" change needed. The 3 callers' adjustments are mechanical bridge drops.

Edit list

  1. Line 92: private var peer: Peer?private var peer: EnginePeer?
  2. Line 521: self.peer = peer?._asPeer()self.peer = peer
  3. Line 2054: peer: EnginePeer(peer),peer: peer,

Total: 3 edits in 1 file.

Out of scope

  • PeerInfoData.swift:355,487 — different classes' self.peer assignments (different types). Audit confirms these are RenderedChannelParticipant.peer and similar — already migrated in earlier waves or owned by other types.
  • PeerInfoAvatarTransformContainerNode.peer (line 223) — already EnginePeer? after wave 46.

Build & verify

source ~/.zshrc 2>/dev/null; \
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

Expected: 1-iteration first-pass-clean. Only PeerInfoScreen + TelegramUI recompile.

Commit

Postbox -> TelegramEngine wave 47. Body lists the 3-edit summary and notes -3 internal bridges.

Outcome capture

Append a Wave 47 entry to docs/superpowers/postbox-refactor-log.md and update memory file project_postbox_refactor_next_wave.md.