Skip to content

fix(chat): remove inter-tile spacing in custom emoji collages - #225

Merged
iebb merged 1 commit into
iebb:masterfrom
TiaraBasori:fix/custom-emoji-collage
Oct 16, 2026
Merged

iebb merged 1 commit into
iebb:masterfrom
TiaraBasori:fix/custom-emoji-collage

Conversation

@TiaraBasori

@TiaraBasori TiaraBasori commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Change

Fix extra horizontal and vertical gaps between consecutive custom (premium) emoji tiles in message text and rich text surfaces so multi-emoji collages/banners (such as bandage/sticker-grid combinations) render seamlessly without visual splitting (all platforms):

  • lib/chat/message_bubble.dart:
    • Remove the Padding(padding: EdgeInsets.symmetric(horizontal: 0.5)) wrapper around SelectableCustomEmojiView in _textSegmentSpans, which previously injected a 1px horizontal gap between every adjacent custom emoji.
    • Round the custom emoji tile dimension (math.max(20, (fontSize * 1.15).roundToDouble())) so PlaceholderAlignment.middle baseline positioning does not suffer from fractional half-pixel rounding drift against integer font metrics.
    • When a rendered paragraph contains custom emoji entities, apply height: 1.0 and TextHeightBehavior(applyHeightToFirstAscent: false, applyHeightToLastDescent: false, leadingDistribution: TextLeadingDistribution.even) on the RichText so multi-row custom emoji collages stack flush vertically without extra font ascent/descent leading gaps.
  • lib/chat/telegram_rich_text.dart:
    • Match custom emoji sizing (math.max(20, (ambientScaler.scale(rawFontSize) * 1.15).roundToDouble())), invalidate _spanCache when MediaQuery.textScalerOf(context) changes, and apply the same tight line-height + TextHeightBehavior when custom emoji entities are present so channel/topic posts, Moments, and album captions render custom emoji collages seamlessly too.
  • lib/chat/custom_emoji.dart:
    • Set textScaler: TextScaler.noScaling on the transparent selection-fallback Text inside SelectableCustomEmojiView so ambient text scaling cannot double-scale the hidden fallback paragraph beyond its pre-scaled size box.

Telegram API Terms classification

Follow the contribution and agentic review rules. Select exactly one classification and explain it below.

This is an agentic source-code review classification. Every store version must remain compliant with applicable Telegram API Terms; the guarded-source exception does not apply to store distribution or review.

  • Compliant/unchanged: this change complies with applicable Telegram API Terms, preserves Telegram's basic functionality, and does not introduce behavior covered by section 1.4.
  • Section 1.4 exception: the entire feature is guarded by allowTelegramTosViolations (I_DONT_FUCKING_CARE_ABOUT_TOS), disabled in official builds, and available only in an explicitly enabled self-build.
  • Disallowed or unresolved: this PR must not be approved or merged until its classification and implementation are resolved.

Reason and affected Telegram behavior:
Pure client-side text/emoji layout fix for textEntityTypeCustomEmoji WidgetSpan rendering. It does not affect Telegram protocol behavior or any Section 1.4 functionality.

Basic checks (every PR)

Check each item after verification. If a check is inapplicable, explain why in the evidence below before checking it.

  • I reviewed the diff for correctness, unintended behavior, secrets, and unrelated changes.
  • Formatting passed, or I recorded why it is inapplicable: dart format --output=none --set-exit-if-changed lib test integration_test test_driver.
  • Analysis passed, or I recorded why it is inapplicable: flutter analyze.
  • Relevant tests passed, or I recorded why they are inapplicable; name the commands and test cases below. Quality CI runs flutter test --concurrency=4.
  • I checked affected build/platform paths and applicable localization/generated files; list the evidence below.
  • I completed the Terms classification above and verified that official builds cannot enable section 1.4 exceptions.

Commands, results, platform/build/UI evidence, and reasons for inapplicable checks:

  • Diff stat (git show --stat HEAD @ 98c5aac4):
    lib/chat/custom_emoji.dart (+1/-0), lib/chat/message_bubble.dart (+27/-11), lib/chat/telegram_rich_text.dart (+34/-6), test/telegram_rich_text_test.dart (+148/-0).
  • Formatting:
    ~/.cache/dart3122/bin/dart format --output=none --set-exit-if-changed lib/chat/custom_emoji.dart lib/chat/message_bubble.dart lib/chat/telegram_rich_text.dart test/telegram_rich_text_test.dart → Formatted 4 files (0 changed).
  • Analysis:
    /tmp/flutter-3.44.2/bin/flutter analyze lib/chat/custom_emoji.dart lib/chat/message_bubble.dart lib/chat/telegram_rich_text.dart test/telegram_rich_text_test.dart → No issues found!.
  • Tests (proven failing-first on pre-fix head: both new collage geometry tests failed before the fix due to 1.0px horizontal gap and 2.25px vertical gap; all 33 tests across telegram_rich_text_test.dart and message_bubble_swipe_reply_test.dart and 32 in desktop_message_quote_test.dart + rich_text_text_scaler_test.dart pass with the fix):
    /tmp/flutter-3.44.2/bin/flutter test --no-pub -j 1 test/telegram_rich_text_test.dart test/message_bubble_swipe_reply_test.dart → 00:15 +33: All tests passed!.
    /tmp/flutter-3.44.2/bin/flutter test --no-pub -j 1 test/rich_text_text_scaler_test.dart test/desktop_message_quote_test.dart → All tests passed!.
    New test cases in test/telegram_rich_text_test.dart:
    • MessageBubble lays out consecutive custom emoji collages flush horizontally and vertically
    • TelegramRichText lays out consecutive custom emoji collages flush horizontally and vertically
  • Localization & registration anchor checks:
    • python3 tool/check_l10n_strings.py → No visible UI string literals outside lib/l10n.
    • python3 translations/tools/check.py → 8 locales x 3829 keys (11 counted): OK
    • python3 translations/tools/gen_assets.py --check → 9 locale assets are up to date
    • python3 tool/gen_registration_anchors.py --check → passed (exit 0).

Section 1.4 exception checks

Complete every item for an exception. For a compliant/unchanged PR, write Not applicable here.

Not applicable

  • All UI, routes, commands, callbacks, background work, TDLib/native effects, and registrations use the compile-time guard; a runtime preference alone cannot enable the feature.
  • With the flag omitted, the feature is absent and ordinary Telegram behavior remains intact, including with old saved settings.
  • With --dart-define=I_DONT_FUCKING_CARE_ABOUT_TOS=false, the feature is absent and ordinary Telegram behavior remains intact.
  • With --dart-define=I_DONT_FUCKING_CARE_ABOUT_TOS=true, the feature works through the guarded entry points in a self-build; I included relevant test and build/UI evidence.
  • Official release, nightly, TestFlight, and store builds keep the flag false and have no option that enables it. All store versions remain compliant with applicable Telegram API Terms.

Guard locations and evidence for each flag variant:
Not applicable

Agentic reviewer confirmation

Agentic code reviewer only: record this confirmation in the PR review or check these boxes before approval.

  • I independently confirmed the Terms classification and inspected all required guards and evidence.
  • Applicable checks and Quality CI pass; no unresolved classification or unguarded section 1.4 behavior remains.

@iebb iebb left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 98c5aac against current master f311e34. The current PR-body update only corrects diff statistics; no source or head change. Independently replayed the new geometry tests on unchanged master: MessageBubble has the 1px horizontal gap and TelegramRichText the 2.25px vertical gap; both fail before the fix and pass after it. All 66 focused collage, spoiler, source-offset/desktop quote, rich-text scaling, and swipe tests pass. The change removes wrapper spacing and corrects the owned emoji/paragraph metrics without adding component/icon assets.

Independently reviewed the actual production diff and affected entry points. The completed contribution template is present; classification is compliant/unchanged, with no Section 1.4 feature or required exception guard. No authentication, protocol/native, storage-schema, release/deployment, or official-build flag path changes. Credential-free snapshots use secrets_example.dart only. The combined intended master tree 6202d9cf8812ed9ca91a39422039a4cfbcee0102 passes all 3,449 unit/widget tests (one existing skip), formatting of 999 files with zero changes, full analysis, 8 locales x 3830 keys / 9 generated locale assets, visible-string and registration checks, and explicit false/true/invalid build-flag tests. Current exact-head Quality is green. Platform evidence here is shared Flutter layout/navigation/selection testing, not native-device QA; no Telegram, real account, deployment, or store action was used.

@iebb
iebb merged commit d4c7463 into iebb:master Oct 16, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants