Commit graph

30074 commits

Author SHA1 Message Date
isaac
0fd2765908 DecryptMatch: pure-Python port of fastlane match decrypt.rb
Replace the Ruby decrypt.rb shell-out with a direct Python call to
decrypt_match_data(). The iOS build no longer depends on a Ruby
interpreter. Includes the spec, plan, AES-256 port, tightened error
surfaces for key length and V1 fallback, and the BuildConfiguration
wire-up that drops decrypt.rb.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 18:45:34 +02:00
Isaac
34c2c8c8a4 Postbox -> TelegramEngine wave 10: StorageFileListPanelComponent drop
Closes the last future-wave candidate from wave 8 by eliminating the
Icon.media(Media, ...) enum case in StorageFileListPanelComponent.swift
and dropping import Postbox. StorageUsageScreen (the module as a whole)
is now fully Postbox-free.

Icon enum split:
  case media(Media, TelegramMediaImageRepresentation)  ->
    case mediaFile(TelegramMediaFile, TelegramMediaImageRepresentation)
    case mediaImage(TelegramMediaImage, TelegramMediaImageRepresentation)

Equatable rewritten as switch-over-tuple with id-based equality per
concrete type (lFile.fileId == rFile.fileId / lImage.imageId ==
rImage.imageId), same semantics as the old media.id comparison.

Binding site: `if case let .media(media, representation)` +
`as? TelegramMediaFile` / `as? TelegramMediaImage` downcasts ->
compound case-binding `case let .mediaFile(_, representation), let
.mediaImage(_, representation):` to lift the shared representation
variable, plus an inner switch for the setSignal branch. The compiler-
enforced exhaustiveness of the split improves call-site safety.

Construction sites (2): `.media(file, representation)` -> `.mediaFile(
file, representation)`, `.media(image, representation)` -> `.mediaImage(
image, representation)`.

Placeholder fixup:
  messageId: EngineMessage.Id(peerId: PeerId(namespace: PeerId.Namespace
    ._internalFromInt32Value(0), id: PeerId.Id._internalFromInt64Value(0)
    ), namespace: 0, id: 0)
  ->
  messageId: EngineMessage.Id(peerId: component.context.account.peerId,
    namespace: 0, id: 0)

Inside a measureItem layout-measurement instance. Caught by second-pass
build failure `cannot find 'PeerId' in scope`. PeerId / PeerId.Namespace
/ PeerId.Id are raw Postbox types (not TelegramCore typealiases —
consistent with wave 9's MessageId -> EngineMessage.Id fixup). Using
context.account.peerId is semantically equivalent for the measurement
use case (messageId only feeds image-fetch userLocation and Equatable
comparison, neither exercised for this standalone instance).

Net: 1 file changed, +22 / -29 lines.

Plan: docs/superpowers/plans/2026-04-20-postbox-to-telegramengine-wave-10.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 01:46:18 +02:00
Isaac
1a432362a3 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>
2026-04-20 01:11:50 +02:00
Isaac
635d392484 Postbox -> TelegramEngine wave 8: StorageUsageScreen domain-type migration
Narrow consumer-module migration of raw Message types to EngineMessage in
the StorageUsageScreen component. Two files touched; the module keeps
import Postbox because of two out-of-scope site clusters (preferences-
view observation + a Media-carrying Icon enum case) — both flagged in
CLAUDE.md and the wave doc as future-wave targets.

StorageUsageScreen.swift:
  SelectionState.togglePeer(availableMessages:)
      [EngineMessage.Id: Message]  -> [EngineMessage.Id: EngineMessage]
  AggregatedData.messages
      [MessageId: Message]         -> [EngineMessage.Id: EngineMessage]
  AggregatedData.clearIncludeMessages / .clearExcludeMessages
      [Message]                     -> [EngineMessage]
  AggregatedData.init messages param — same swap
  RenderResult.messages
      [MessageId: Message]         -> [EngineMessage.Id: EngineMessage]
  openMessage(message: Message)    -> openMessage(message: EngineMessage)
                                      (unwrap to raw at OpenChatMessageParams
                                       / chatMediaListPreviewControllerData
                                       call sites via ._asMessage())

StorageFileListPanelComponent.swift:
  Item.message: Message            -> EngineMessage
                                      (internal .id / .timestamp / .media
                                       usage compiles unchanged against the
                                       EngineMessage class).

Wave-7 facade-boundary bridging dropped:
  - renderStorageUsageStatsMessages call site: the .mapValues(EngineMessage.init)
    on existingMessages and .mapValues { $0._asMessage() } on the result vanish;
    AggregatedData.messages and RenderResult.messages are now engine-typed on
    both sides of the facade.
  - clearStorage call sites (2): the .map(EngineMessage.init) wraps around
    includeMessages / excludeMessages vanish; locals become [EngineMessage].
  - Inside AggregatedData.updateSelected... accumulation loop, four
    item.message._asMessage() calls (where item.message was EngineMessage
    and the target was [Message]) drop back to plain item.message.
  - StorageMediaGridPanelComponent.Item(message: EngineMessage(message), ...)
    at the RenderResult-build loop loses the EngineMessage(...) wrap since
    `message` is already EngineMessage.

Out of scope (module keeps import Postbox):
  - StorageUsageScreen.swift:1047-1062 / 3131-3185 — AccountSpecificCache-
    StorageSettings observation via postbox.combinedView + PreferencesView
    and a postbox.transaction block doing transaction.getPeer / getPeerCached-
    Data as? CachedGroupData/CachedChannelData for peer-category classification.
  - StorageFileListPanelComponent.swift:105 — Icon.media(Media, ...) enum case.
    Constructed only as .media(TelegramMediaFile, ...) or .media(TelegramMedia-
    Image, ...); trivial future wave to split into two cases.

Build verified green: 59s incremental, 27 actions, Telegram.ipa produced.

Plan: docs/superpowers/plans/2026-04-20-postbox-to-telegramengine-wave-8.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 00:39:19 +02:00
Isaac
b2ba4b5878 Postbox -> TelegramEngine wave 7: last TelegramEngine.* facade leaks
Closes the seven remaining raw-Postbox leaks in TelegramEngine public
facades surfaced by a post-wave-6 scouting pass (all non-permanently-
blocked candidates).

Facades migrated in place (6 rewrites + 1 deletion; all _internal_*
implementations unchanged per the "internal Postbox-facing stays raw"
rule):

  Messages:
    downloadMessage                          Signal<Message?>           -> Signal<EngineMessage?>
    topPeerActiveLiveLocationMessages        Signal<(Peer?, [Message])> -> Signal<(EnginePeer?, [EngineMessage])>
    getSynchronizeAutosaveItemOperations     deleted (dead facade; sole caller uses _internal_ directly)

  Peers:
    updatedRemotePeer                        Signal<Peer>  -> Signal<EnginePeer>
                                             (PeerReference param kept; no EnginePeer.Reference alias today)

  Resources:
    renderStorageUsageStatsMessages          [EngineMessage.Id: Message]  -> [EngineMessage.Id: EngineMessage]
    clearStorage(peerId: ...)                [Message]                     -> [EngineMessage]
    clearStorage(peerIds: ...)               [Message]                     -> [EngineMessage]
    clearStorage(messages:)                  [Message]                     -> [EngineMessage]
                                             (no external callers; migrated for overload-set consistency)

Consumer call-site updates (5 files):
  - ChatListSearchListPaneNode       drop redundant .flatMap(EngineMessage.init) wrap
  - LocationViewControllerNode       drop redundant .map(EngineMessage.init) wrap
  - LiveLocationSummaryManager       drop redundant EnginePeer(...) / EngineMessage(...) ctors
  - StorageUsageScreen               bridge [Message] <-> [EngineMessage] at the 4 facade-call points
                                     (internal [MessageId: Message] / [Message] storage kept;
                                      full-consumer-module migration is out of scope)

Discovery: grep of TelegramEngine/*/TelegramEngine*.swift public signatures
for `: Postbox|: Account|: MediaBox|: MediaResource|: Peer\b|: Message\b|
-> Signal<.*(Peer|Message)` turned up these seven candidates and no others.
After this wave, the full TelegramEngine.* facade surface is engine-typed
modulo the four permanently-blocked TelegramMediaResource-conforming
classes recorded in CLAUDE.md (ICloudFileResource, InstantPageExternal-
MediaResource, VideoLibraryMediaResource, YoutubeEmbedStoryboardMedia-
Resource).

No modules became Postbox-free in this wave. Plan: docs/superpowers/
plans/2026-04-20-postbox-to-telegramengine-wave-7.md.

Full project build verified green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 00:25:28 +02:00
Isaac
31012e7cf9 CLAUDE.md: update wave-6 commit SHA references after squash
The wave-6 commits (spec, plan, C1 batch drop, C2 tally) were
squashed into a single commit, shifting the SHA referenced twice in
the wave-6 outcome section. Updates the two "see git show <sha>"
pointers to the new squashed commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:55:25 +02:00
Isaac
8edaa79eda Merge commit '23c4d94748' 2026-04-19 23:54:22 +02:00
Isaac
7b2b74e79b Postbox -> TelegramEngine wave 6: unused import Postbox batch sweep
First build-verified unused-import sweep: speculatively dropped
import Postbox from 782 consumer files (plain ^import Postbox$ lines,
excluding TelegramCore/Postbox/TelegramApi paths), iterated 18 full
project builds with --continueOnError, restored the import on every
file that failed to compile. 183 drops survived; 189 consumer modules
newly Postbox-free.

Bundled: spec + plan + C1 atomic batch drop + C2 CLAUDE.md outcome and
permanent methodology guidance under Wave-selection. The methodology
subsection captures the reusable playbook (--continueOnError is
essential, dependency graphs are deep so expect many iterations,
pattern-based preemptive restores accelerate convergence, and
CLAUDE.md's engine typealias cheat sheet arrows are migration targets
rather than typealiases in TelegramCore).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:46:13 +02:00
Isaac
c99adbbe0b Postbox -> TelegramEngine wave 5: uploadSecureIdFile + SecureId context
Migrates uploadSecureIdFile's public signature from (context:,
postbox: Postbox, network: Network, resource: MediaResource) to
(context:, engine: TelegramEngine, resource: EngineMediaResource).
SecureIdVerificationDocumentsContext refactored to hold
engine: TelegramEngine instead of raw postbox + network, drops
import Postbox (tally +1). The one instantiation site in
SecureIdDocumentFormControllerNode updates to pass
engine: self.context.engine.

Completes the last explicitly-named future-wave candidate from
CLAUDE.md.

Bundled: spec + plan + C1 atomic migration + CLAUDE.md outcome.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:45:59 +02:00
Isaac
b989b160c0 Postbox -> TelegramEngine wave 4: TelegramEngine.Stickers.uploadSticker
Migrates uploadSticker's public surface from (peer: Peer,
resource: MediaResource, thumbnail: MediaResource?, ...) to
(peer: EnginePeer, resource: EngineMediaResource,
thumbnail: EngineMediaResource?, ...), and UploadStickerStatus.complete
payload from CloudDocumentMediaResource to EngineMediaResource. Both
external call sites plus the cascading destructure and .standalone
sites inside MediaEditorScreen migrated atomically.

Bundled: spec + fix + plan + C1 atomic facade migration + CLAUDE.md
outcome + enum-payload inventory lesson added to wave-selection
guidance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:45:48 +02:00
Isaac
4ae15b42a7 Postbox -> TelegramEngine wave 3: MediaBox fetch/status/data facades + SaveToCameraRoll
Adds three thin forwarding methods on TelegramEngine.Resources
(fetch, status, data) over MediaBox, then migrates SaveToCameraRoll's
three public functions to use them, drops import Postbox from the
module (source + Bazel dep), and updates all 23 call sites across 14
caller files atomically.

Bundled: spec + fix + plan + C1 facades + C2 SaveToCameraRoll rewrite
+ BUILD dep drop + CLAUDE.md outcome.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:45:34 +02:00
Isaac
791bb62148 Display/ListView: snap-scroll to pinned item + synchronous history transactions
Adds an experimentalSnapScrollToPinnedItem path that resnaps scroll to
the first pinToEdgeWithInset item after inset/visible-size updates and
on empty itemNodes. Promotes ListViewItem to AnyObject and adds a
pinToEdgeWithInset protocol requirement with a default of false.

Also runs chat history transactions synchronously when updating scroll
around correlated messages, and tightens beganInteractiveDragging weak-
self handling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:45:18 +02:00
Isaac
684796144c TextProcessing: style create/edit/delete, AI previews, and integration
Wires up TextProcessingScreen to the edit/delete AI text style facades,
renders AI text style webpage previews in chat bubbles, and exposes a
shared makeEmojiStatusSelectionController on SharedAccountContext so
the screen can present the emoji picker when assigning a style emoji.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:45:18 +02:00
Isaac
d01bbc6529 TelegramCore: edit/delete AI text styles + AI webpage attribute
Adds TelegramEngine.Messages.editAITextStyle and deleteAITextStyle
facades and decodes webPageAttributeAiComposeTone into a new
TelegramMediaWebpageAITextStyleAttribute. Makes CloudStyle.prompt
optional and requires emojiFileId on create.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:45:18 +02:00
Isaac
b8e985b939 TelegramApi: regenerate schema for AI-compose tone + webpage attribute
Adds aicompose.createTone/updateTone/deleteTone functions,
InputAiComposeTone constructor, and webPageAttributeAiComposeTone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:45:18 +02:00
Isaac
4bd54b9771 Display/ListView: pin first pinToEdgeWithInset item to bottom edge
Introduces a pin-to-edge mode for list items: items whose
pinToEdgeWithInset flag is true are pinned to the bottom edge of the
visible area, with the list geometry (pin inset, scrollToItem,
inset-transition offsetFix, visible-size updates) adjusted to handle
this new mode consistently.

Collected from spec, plan, and 12 iterative fixes during
implementation that refined pin-inset helpers, scroll landings, and
transition math. Pin-inset computation uses frame.size.height;
scrollToItem lands on the item's pinned position via apparentBounds.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 23:45:13 +02:00
Ilya Laktyushin
23c4d94748 Various fixes 2026-04-19 21:50:24 +02:00
Ilya Laktyushin
1670677a92 Various fixes 2026-04-19 21:48:47 +02:00
Ilya Laktyushin
b138b9f549 Stickers & emoji search pagination 2026-04-19 18:32:40 +02:00
Ilya Laktyushin
c9b76c9294 Various fixes 2026-04-19 14:17:48 +02:00
Ilya Laktyushin
d88a29b378 Various improvements 2026-04-18 08:41:08 +02:00
Ilya Laktyushin
1fa0c7991c Various fixes 2026-04-17 11:06:56 +02:00
Isaac
bedbc8de6d CLAUDE.md: record wave-2 outcome and update wave-selection guidance
Reflects the current state of the Postbox → TelegramEngine refactor:

- Header now lists waves 1 and 2 with their plans.
- New "Wave 2 outcome (2026-04-17)" section enumerates the five
  migrated TelegramEngine facades, the one fully de-Postboxed
  consumer submodule (MapResourceToAvatarSizes), the AuthorizationUI
  signal type swap, and the abandoned Task 8 (SaveToCameraRoll).
- Wave-selection guidance extended with two lessons learned:
  (a) planning-time inventories should grep the full Postbox token
  set, not just the tokens specific to the wave's goal, to avoid
  execution-time abandonments like wave 2's SaveToCameraRoll; and
  (b) facade-API migrations (wave 2's shape) work better than
  per-module Postbox drops (wave 1's shape) when the target is a
  shared API surface.
- New "Modules currently free of import Postbox" tally lists the
  8 consumer modules now clean across all waves and the standalone
  PromptUI / PresentationDataUtils / StickerPeekUI cleanups.
- New "Known future-wave candidates" section records the three
  leaks surfaced by the wave-2 final review and the four permanently
  blocked TelegramMediaResource-conforming classes.

Docs-only change. No behavior change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 09:43:48 +02:00
Isaac
bbfd1ddca0 Merge commit '532a3ae3e1' 2026-04-17 09:09:55 +02:00
Isaac
f84e94f507 MediaResource → EngineMediaResource refactor: wave 2
Drive raw `MediaResource` out of the `TelegramEngine` public facade for
photo-upload APIs, and complete a first batch of consumer-side
migrations. Behavior-preserving. The `_internal_*` Postbox-facing
functions are untouched — only the facade signatures change, bridging
inside via `_asResource()` / `EngineMediaResource(_:)`.

TelegramEngine facades migrated (signatures now take EngineMediaResource):
- TelegramEngine.Peers.uploadedPeerPhoto / uploadedPeerVideo
- TelegramEngine.Peers.updatePeerPhoto (closure param too)
- TelegramEngine.AccountData.updateAccountPhoto / updateFallbackPhoto
- TelegramEngine.Contacts.updateContactPhoto
- TelegramEngine.Auth.uploadedPeerVideo

Consumer-side changes:
- MapResourceToAvatarSizes utility: signature is now
  (engine: TelegramEngine, resource: EngineMediaResource, ...). Uses
  engine.resources.data(id:) internally. The submodule drops
  `import Postbox` and the Bazel dep.
- AuthorizationUI: avatar-video signal retyped from
  Signal<TelegramMediaResource?> to Signal<EngineMediaResource?>.
- 27 `mapResourceToAvatarSizes(postbox:...)` call sites across 5
  TelegramUI/TelegramCallsUI files migrated to the new form.

Deferred:
- SaveToCameraRoll (planned Task 8) abandoned — module has three
  public functions taking `postbox: Postbox` (umbrella-type leak,
  banned by rule 2) and requires a full module-migration wave, not a
  type swap. Reason recorded in the wave-2 plan doc.
- Other TelegramEngine facades still leaking MediaResource
  (TelegramEngineStickers.uploadSticker; UploadSecureIdFile.* —
  additionally leaks Postbox) flagged for a future wave.

Docs:
- CLAUDE.md: new rule 7 (TelegramCore never imports UIKit/Display,
  shared with Telegram-Mac), and a new "MediaResource →
  EngineMediaResource consumer migration" section describing the
  wrap/unwrap helpers and the modify-in-place facade-bridging
  pattern.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 09:07:54 +02:00
Isaac
adc275af27 Fix base64 2026-04-17 09:06:14 +02:00
Isaac
75ec477248 PresentationDataUtils: drop direct Postbox dependency
The only Postbox usage in Sources/ was a `PeerId?` parameter in the
public signature of openUserGeneratedUrl. Switch to the
EnginePeer.Id typealias (same type as PeerId, so no call sites
break) and remove the Postbox import. Add TelegramCore to BUILD
deps since EnginePeer lives there; Postbox was not in BUILD (was
transitively supplied). Behavior-preserving.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 23:55:52 +02:00
Isaac
ef0974de6d PromptUI: drop unused Postbox dependency
The `import Postbox` line and `//submodules/Postbox` BUILD dep were
unused — no Postbox types or APIs are referenced in the module.
Removing both. Behavior-preserving.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 23:55:48 +02:00
Isaac
10e40b974c StickerPeekUI: drop unused Postbox dependency
The `import Postbox` line and `//submodules/Postbox` BUILD dep were
unused — no Postbox types or APIs are referenced in the module.
Removing both. Behavior-preserving.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 23:37:44 +02:00
Isaac
ad85ef6517 Postbox → TelegramEngine refactor: wave 1
Drop direct `import Postbox` from four leaf consumer submodules, routing
data access through TelegramEngine/TelegramCore. Behavior-preserving.

Consumers migrated:
- ChatInterfaceState
- ChatSendMessageActionUI
- ContactListUI
- DrawingUI

TelegramCore additions (typealiases + one EngineData item):
- EngineMemoryBuffer, EnginePostboxDecoder, EnginePostboxEncoder,
  EngineAdaptedPostboxDecoder (narrow utility aliases for coding support)
- EngineData.Item.Configuration.ContactsSettings

Six planned modules were abandoned in wave 1 with reasons recorded in
the plan: ActionSheetPeerItem, ChatListSearchRecentPeersNode,
DirectMediaImageCache, FetchManagerImpl, GalleryData, ICloudResources.
Each either has a public API that leaks `Postbox`/`Account`/`MediaBox`
(banned umbrella-type aliases) or cascades into out-of-wave modules.

CLAUDE.md now records the wave rules, typealias cheat sheet, and the
wave-selection guidance learned from this pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 23:16:45 +02:00
Ilya Laktyushin
532a3ae3e1 Various fixes 2026-04-16 21:45:26 +02:00
Isaac
40112d3cff Add implementation plan: Postbox → TelegramEngine wave 1
10 tasks, one per chosen leaf module, each with inventory-map-edit-
build-commit steps. Common build command, commit template, and
failure-handling rules centralized in a Background section.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 18:32:51 +02:00
Isaac
ec24ec7dbb Tighten wave-1 spec: clarify engine typealias rules
TelegramCore does not re-export Postbox, so dropping the Postbox
import forces every Postbox-type reference to switch to an engine
typealias. Spell this out, and clarify that new typealiases are in
scope while new engine wrapper structs are not.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 18:24:13 +02:00
Isaac
5d40b8ca33 Add design: Postbox → TelegramEngine refactor, wave 1
Covers the first 10 single-import leaf submodules, in bottom-up
dependency order, with full-build verification per module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 18:22:52 +02:00
Isaac
bf21bca206 Merge commit '31e3a7dc79'
# Conflicts:
#	submodules/TelegramCore/Sources/PendingMessages/PendingMessageUploadedContent.swift
#	submodules/TelegramCore/Sources/TelegramEngine/Messages/Polls.swift
#	submodules/TelegramCore/Sources/TelegramEngine/Messages/Translate.swift
2026-04-16 17:52:38 +02:00
Ilya Laktyushin
31e3a7dc79 Fix build 2026-04-16 02:36:03 +02:00
Ilya Laktyushin
8aa421e08b Fix build 2026-04-16 02:00:16 +02:00
Ilya Laktyushin
8b7e294fc6 Fix build 2026-04-16 01:41:31 +02:00
Ilya Laktyushin
0df319742a Update API 2026-04-16 01:18:22 +02:00
Ilya Laktyushin
efb1110987 Fix build 2026-04-16 00:20:06 +02:00
Ilya Laktyushin
352d9f24e8 Fix build 2026-04-16 00:03:09 +02:00
Ilya Laktyushin
701d27c0a9 Fix build 2026-04-15 23:50:11 +02:00
Ilya Laktyushin
8f1e024aef Various fixes 2026-04-15 23:12:53 +02:00
Isaac
0095bfad39 Temp 2026-04-15 13:18:46 +02:00
Isaac
a4e9b0468e Merge commit '314f02d36d' 2026-04-14 15:34:04 +02:00
Isaac
2de1052c3d Cleanup 2026-04-14 15:33:58 +02:00
Isaac
976c2de599 Temp 2026-04-14 15:33:19 +02:00
Isaac
430ea53ed8 Add per-character glyph rects to InteractiveTextNodeLine and implement reveal animation
- Replace characterToGlyphMapping with characterRects ([CGRect]?) on InteractiveTextNodeLine
- Add computeCharacterRects flag to InteractiveTextNodeLayoutArguments
- Compute actual glyph bounding boxes via CTFontGetBoundingRectsForGlyphs during layout
- Implement computeRevealedLines, layoutForCharacterCount, sizeForCharacterCount
- Implement updateRevealCharacterCount to distribute character budget across content item layers
- Update snippet layers to animate per-character rects with SnippetLayer tracking character index
- Mask limit driven by lowest animating snippet index for correct reveal ordering
- Fix listViewAnimationCurveEaseIn to match iOS default ease-in curve (0.42, 0.0, 1.0, 1.0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 15:31:49 +02:00
Isaac
9fb219645b Add design spec for character rects in InteractiveTextNodeLine
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:24:54 +02:00
Ilya Laktyushin
314f02d36d Various fixes 2026-04-14 04:53:01 +02:00