From b9c8b1177e31fb602a799e67cae9618a76f993ef Mon Sep 17 00:00:00 2001 From: Exotic209093 <134711311+Exotic209093@users.noreply.github.com> Date: Sun, 13 Sep 2026 19:24:19 +0100 Subject: [PATCH] fix(mobile): prevent text clipping on iOS chat messages Fixes #11200 --- .../ios/T3MarkdownTextShadowNode.mm | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/mobile/modules/t3-markdown-text/ios/T3MarkdownTextShadowNode.mm b/apps/mobile/modules/t3-markdown-text/ios/T3MarkdownTextShadowNode.mm index b9abe452fb94..8432c285a610 100644 --- a/apps/mobile/modules/t3-markdown-text/ios/T3MarkdownTextShadowNode.mm +++ b/apps/mobile/modules/t3-markdown-text/ios/T3MarkdownTextShadowNode.mm @@ -241,13 +241,26 @@ static void applyAttachments( [layoutManager ensureLayoutForTextContainer:textContainer]; const CGRect usedRect = [layoutManager usedRectForTextContainer:textContainer]; + // NSLayoutManager with usesFontLeading=NO can underreport height by up to + // one line's worth of leading, causing text to be clipped at the bottom of + // its container on iOS. Adding a fraction of the base line height as a + // buffer ensures the measured size always encompasses the rendered glyphs. + Float heightBuffer = 0; + if (!baseAttributedString.isEmpty()) { + const auto &firstFragment = baseAttributedString.getFragments().front(); + const Float lineHeight = firstFragment.textAttributes.lineHeight.value_or(0); + if (lineHeight > 0) { + heightBuffer = lineHeight * 0.15f; + } + } + return { std::clamp( static_cast(std::ceil(usedRect.size.width)), layoutConstraints.minimumSize.width, layoutConstraints.maximumSize.width), std::clamp( - static_cast(std::ceil(usedRect.size.height)), + static_cast(std::ceil(usedRect.size.height + heightBuffer)), layoutConstraints.minimumSize.height, layoutConstraints.maximumSize.height), };