Commit graph

30443 commits

Author SHA1 Message Date
isaac
758e596bf9 InstantPage: add code-block text style for rich messages
Local in-progress work (committed at the author's request as a checkpoint
before unrelated true-font-height work lands on top): introduces a
dedicated `codeBlock` InstantPage font/text style (.monospace / .codeBlock
font cases + monospace font resolution), adds a `codeBlock` field to the
InstantPage text-attributes theme and threads it through the rich-data
bubble and the send preview, and unifies the rich-bubble code-block
background/secondary-control colors.
2026-06-01 02:14:59 +02:00
isaac
5893b574a8 Add implementation plan: V2 text items as true font-height line boxes
Task 1: 3-line metric change in layoutTextItem (topInset shift + descender
pad). Task 2: re-tune the streaming chat-bubble bottom inset (the now-
contained descender makes the +6.0 hack partly redundant). Task 3: broad
visual verification of the remaining consumers (decorations, reveal mask,
lists, blockquotes, tables, title) with one gated table-inset fix. Task 4:
spec acceptance checklist. Verification model adapted to this repo: full
Bazel build + simulator visual checks (no unit tests exist).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 02:07:03 +02:00
isaac
625aac9294 Add design spec: V2 text items as true font-height line boxes
Approach 2 (true proper line box): shift the line stack down by the
ascender headroom (exact A - L, not pixel-snapped) and pad the returned
height by the last line's descender, so a single-line V2 text item
measures exactly the true font height (A + D) instead of the cap box
(A - D). Inter-line advance unchanged; formulas still inflate.
Documents the affected height/frame consumers (chat-bubble height +
status node, streaming clip, table cells, title centering, reveal cost)
and the verification plan.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 01:59:38 +02:00
isaac
9205fb2303 Fix inline emoji/image line-height inflation in InstantPage V2
The V2 line-breaker used `lineAscent` as both the line height and the
baseline offset, then inflated it to each inline emoji/image's full visual
size and bottom-aligned the attachment on that inflated baseline. A 24pt
emoji on a ~17pt line therefore doubled the line height and shoved the
text baseline (and all text on the line) down.

Stop inflating the line for emoji/images (only formulas, which carry their
own metrics, still grow it) and center each attachment on the font line
box at `baselineY - fontLineHeight/2 - size/2`, matching V1
`layoutTextItemWithString` and the chat `InteractiveTextComponent`. The
attachment now bleeds symmetrically instead of moving the baseline.
`extraDescent` absorbs tall-attachment bottom overflow so the next line is
not overlapped, and the streaming-reveal `characterRect` is centered in
lockstep so the reveal mask tracks the cell (reveal cost stays width-only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 18:28:05 +02:00
isaac
a3492c0cb0 Update tgwatch 2026-05-31 18:13:57 +02:00
isaac
750911ce3c Merge commit '14ade58f34' 2026-05-31 18:05:01 +02:00
isaac
471ae08219 Merge commit 'e2de53ea17' 2026-05-31 18:04:21 +02:00
isaac
14ade58f34 Merge commit 'e2de53ea17' 2026-05-31 18:00:47 +02:00
isaac
6bcf266118 Remove stop button 2026-05-31 18:00:38 +02:00
isaac
ef2c1d47cc Revert "Update tgwatch signing"
Revert the universal/dynamic watch bundle id change (commit 1120b9084e)
back to the static 0682 shape, for install testing.

This reverts the PRODUCT_BUNDLE_IDENTIFIER override + $(...:base) companion-id
derivation; the watch app again bakes the hardcoded ph.telegra.Telegraph.watchkitapp
and literal WKCompanionAppBundleIdentifier=ph.telegra.Telegraph.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 17:58:30 +02:00
isaac
3ed8c926a8 Custom emoji in markdown rich messages (send + round-trip)
Parse custom emoji into RichText.textCustomEmoji when sending markdown
rich messages, and round-trip them through edit, copy, and paste using a
shared tg://emoji?id=<fileId> markdown-link marker.

- Send: rewrite each customEmoji input attribute into a
  [<alt>](tg://emoji?id=<fileId>) marker before the CommonMark parse, then
  intercept the marker URL afterward to emit .textCustomEmoji. Only rich
  messages are affected; a custom emoji alone stays on the entity path.
- Reverse: InstantPageToMarkdown (whole-message copy + edit reconstruction)
  and InstantPageMultiTextAdapter (selection copy) emit the marker;
  edit-load and chat paste reattach it as a live customEmoji attribute.
- Marker helpers shared in TextFormat/CustomEmojiMarkdownMarker.swift.
- Rich sends now pass inlineStickers so recipients can fetch the files.

Follow-up to verify at runtime: recipient rendering goes out with
Api.InputRichMessage.documents: nil; if recipients see only the fallback
glyph, populate documents: in apiInputRichMessage().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 17:51:37 +02:00
Ilya Laktyushin
e2de53ea17 Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios 2026-05-31 17:35:39 +02:00
Ilya Laktyushin
622f9d970a Various fixes 2026-05-31 17:35:32 +02:00
isaac
6408175725 InstantPage V2 thinking block: text-item sizing, overhang, inline emoji/images
Make the thinking block render consistently with a normal text item:

- Size the `.thinking` item frame text-width at the page inset
  (`(horizontalInset, 0, textWidth, height)`), identical to a `.text`
  item, instead of a full-bleed `(0, 0, boundingWidth, height)` box, by
  laying the text out flush and moving the inset onto the block frame.
  The shimmer (sized to `item.frame.size`) now hugs the text.

- Size the shimmer + its gradient mask to the clipping-inset-expanded
  frame (shifted `-inset`) so the mask no longer crops glyph ascenders,
  descenders and the last line's underline, mirroring how a `.text`
  view's frame is inset-expanded.

- Visit the thinking block's shimmer-wrapped inner text view in
  updateInlineEmoji / updateInlineImages so its inline custom emoji and
  images get layers created, positioned and revealed. They were skipped
  because the page only iterated top-level InstantPageV2TextView items.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 15:49:33 +02:00
isaac
1120b9084e Update tgwatch signing 2026-05-31 15:34:43 +02:00
isaac
d4736fe59f Revert tgwatch signing 2026-05-31 15:04:50 +02:00
isaac
f6dc52c533 Update layout 2026-05-30 23:27:26 +02:00
isaac
3525bcacb2 Add watch profile guard 2026-05-30 22:16:10 +02:00
isaac
dbd53522be Merge commit '98d148e08d' 2026-05-30 18:49:56 +02:00
isaac
eb1b918a77 InstantPage V2 table: cell layout polish (insets, text category, border width)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:47:04 +02:00
isaac
3d9fbdec3c InstantPage V2 table: rounded corners and corner-cell fill rounding
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:47:04 +02:00
isaac
79bcc7bc34 InstantPage V2 table: flush frame, inset borders
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:47:03 +02:00
isaac
e8de87dc7b InstantPage V2: render server-sent thinking blocks
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 18:47:03 +02:00
Ilya Laktyushin
98d148e08d Various fixes 2026-05-29 16:46:38 +02:00
isaac
484b66f28c Add implementation plan: InstantPage V2 thinking-block + cross-update view reuse
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 16:36:40 +02:00
isaac
a50f40476d Add design spec: InstantPage V2 thinking-block rendering + cross-update view reuse
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 16:28:37 +02:00
isaac
79ee96306b Update tgwatch 2026-05-29 16:08:23 +02:00
isaac
354e1c7a66 Implement InstantPageBlock.thinking (pageBlockThinking) parsing & serialization
Add a first-class InstantPageBlock.thinking(RichText) case mirroring .kicker:
- enum case + InstantPageBlockType.thinking = 30; Postbox coding & equality
- FlatBuffers InstantPageBlock_Thinking schema (appended last) + Swift codecs
- API parse at InstantPage.swift; output-only on send (apiInputBlock returns nil)
- no-op stubs in the two exhaustive switches (preview text, V2 layout)

Rendering is out of scope. Verified by a full Bazel build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 16:07:09 +02:00
isaac
bd8886b0f0 Merge commit '4b2a826682' 2026-05-29 15:47:41 +02:00
isaac
5950bbe8a1 Fix code 2026-05-29 15:47:37 +02:00
isaac
1d8931b334 Render markdown rich-text preview in send-message context screen
When the user long-presses Send in the main chat and the composed text passes the
same rich-markdown gate used at send time (richMarkdownAttributeIfNeeded), the
send-options preview bubble renders the message as rich InstantPage content,
crossfading from the raw text as the menu animates in. Plain text and custom chat
contents / edit previews are unchanged.

ChatSendMessageActionUI cannot depend on InstantPageUI (it closes a dependency
cycle via LocationUI -> AttachmentUI -> ... -> ChatTextInputActionButtonsNode), so
the rich view is built in TelegramUI (ChatSendMessageRichTextPreview, wrapping
InstantPageV2View + the outgoing message theme) and injected into the screen via a
new ChatSendMessageContextScreenRichTextPreview protocol, mirroring the existing
media-preview pattern. The main-chat send call site classifies the compose text
and injects the preview; MessageItemView lays it out within the send-button-bounded
bubble envelope and crossfades between the raw text and the rich layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 15:46:16 +02:00
isaac
471d11df16 Copy rich messages as markdown (whole message + partial selection)
Rich messages (RichTextMessageAttribute, text == "") are copyable as
markdown two ways: the context-menu Copy action copies the whole
message, and a text selection inside the rich-data bubble copies just
the selected range. Both reconstruct markdown mirroring the edit
round-trip (markdownStringFromInstantPage).

Implements the full RichText entity case set
(mention/hashtag/cashtag/bot-command/bank-card/auto url/email/phone) with
tap interaction, the InstantPage -> markdown inverse converter and edit
round-trip, markdown-context stamping during V2 layout
(InstantPageMarkdownBlockContext: heading level, list/code/table/quote
depth), partial-selection markdown emission
(InstantPageMultiTextAdapter.markdownForRange), and numerous converter
edge-case fixes (tables, links, fenced code, blockquote line coalescing,
compact nested >> markers).

CLAUDE.md documents the feature; the spec/plan scratch docs generated
during development are not committed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 13:52:47 +02:00
Ilya Laktyushin
4b2a826682 Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios 2026-05-29 10:01:53 +02:00
Ilya Laktyushin
e0f4655cc5 Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios 2026-05-29 09:24:16 +02:00
isaac
65eac2fa94 Update tgwatch 2026-05-29 02:03:31 +02:00
isaac
befacaa5fe InstantPage: distinct per-level heading sizes 2026-05-29 01:54:03 +02:00
isaac
28763bb92d InstantPage blockQuote: nested-blocks payload
Upgrade InstantPageBlock.blockQuote from (text, caption) to
(blocks: [InstantPageBlock], caption). Legacy inbound shapes (API
pageBlockBlockquote, Postbox "t", FlatBuffers text) lift into
[.paragraph(text)]; outbound stays on the legacy wire constructor for
empty/single-paragraph quotes and uses pageBlockBlockquoteBlocks
otherwise. V1/V2 renderers recurse into child blocks with a fixed 10pt
inter-child gap; markdown forward/reverse, entity-expressibility, and
preview text updated. pullQuote is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 01:00:47 +02:00
isaac
ef7d582849 Update consumers for regenerated TL API
Regenerated TelegramApi sources and updated the affected consumers:
- InstantPage ordered-list encode: inputPageBlockOrderedList -> pageBlockOrderedList
- ChatContextResult: handle new constructor (exhaustive switch)
- JoinChannel/JoinLink: chatInviteJoinResultWebView now (botId, webview, users)
- WebUI chat-context-result preview consumers
2026-05-29 00:55:12 +02:00
isaac
54958c5b19 Fix parsing 2026-05-28 23:38:11 +02:00
isaac
4c254fe5b4 Spec: InstantPage blockQuote nested-blocks payload
Upgrades the InstantPageBlock.blockQuote case from a text-only
payload to a nested-blocks payload, covering API parse, Postbox +
FlatBuffers serialization, API encode, V1/V2 layout, markdown
forward/reverse, entity-expressibility, and preview text.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 22:19:28 +02:00
isaac
a2548088f6 Update watch app 2026-05-28 22:07:52 +02:00
isaac
0be58ef45a Enable watch app cache 2026-05-28 21:23:34 +02:00
isaac
3a62d3417f Update tgwatch 2026-05-28 21:10:19 +02:00
isaac
55619c54f9 Fix crash 2026-05-28 19:31:09 +02:00
isaac
a3131ba4d2 Update watch signing 2026-05-28 19:31:00 +02:00
isaac
aa6314e5c4 Fix layout 2026-05-28 19:00:59 +02:00
isaac
045ba10386 Update tgwatch 2026-05-28 19:00:35 +02:00
isaac
8f4f463265 Fix layout 2026-05-28 18:17:02 +02:00
isaac
7b11a88231 Update CI 2026-05-28 17:25:20 +02:00
isaac
dce321c77a Fix build 2026-05-28 17:23:58 +02:00