fix(ios): address clipped chat and Markdown text (#6445)

* Revert "fix(app): reflow iPad chat text after pane resize (#5716)"

This reverts commit 5715b5ba62.

* docs(changelog): describe iOS text clipping fix for 0.11.2

* chore(release): cut 0.11.2
This commit is contained in:
Mohamed Boudra
2026-10-09 16:35:43 +01:00
committed by GitHub
parent 718ed932b7
commit 73390346ca
24 changed files with 77 additions and 230 deletions
@@ -1,72 +0,0 @@
diff --git a/node_modules/react-native-uitextview/ios/RNUITextView.mm b/node_modules/react-native-uitextview/ios/RNUITextView.mm
index d0c31ed..df8a233 100644
--- a/node_modules/react-native-uitextview/ios/RNUITextView.mm
+++ b/node_modules/react-native-uitextview/ios/RNUITextView.mm
@@ -22,6 +22,7 @@ using namespace facebook::react;
RNUITextViewShadowNode::ConcreteState::Shared _state;
UITapGestureRecognizer * _outsideTapRecognizer;
BOOL _suppressSelectionChange;
+ CGRect _lastTextLayoutFrame;
}
+ (ComponentDescriptorProvider)componentDescriptorProvider
@@ -47,7 +48,8 @@ using namespace facebook::react;
_textView.delegate = self;
// Must match RCTTextLayoutManager, which measures with usesFontLeading = NO.
_textView.layoutManager.usesFontLeading = NO;
- [self addSubview:_textView];
+ _textView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+ [_view addSubview:_textView];
const auto longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(handleLongPressIfNecessary:)];
@@ -94,16 +96,15 @@ using namespace facebook::react;
// Reset the frame to zero so that when it properly lays out on the next use
_textView.frame = CGRectZero;
_textView.attributedText = nil;
+ _lastTextLayoutFrame = CGRectZero;
}
- (void)layoutSubviews
{
[super layoutSubviews];
- // _textView's frame is assigned inside drawRect, which only fires when
- // state changes. Trigger a redraw whenever the host frame moves out from
- // under it (rotation, parent relayout) so the text view resizes and
- // onTextLayout re-fires with the new line wrapping.
- if (!CGRectEqualToRect(_textView.frame, _view.frame)) {
+ // Autoresizing updates UIKit immediately; report the new line layout when
+ // the content container's bounds change.
+ if (!CGRectEqualToRect(_lastTextLayoutFrame, _view.bounds)) {
[self setNeedsDisplay];
}
}
@@ -124,8 +125,9 @@ using namespace facebook::react;
// entirely when nothing actually changed so a JS-side state update made in
// response to onSelectionChange doesn't deselect what the user is selecting.
const BOOL textChanged = ![_textView.attributedText isEqualToAttributedString:convertedAttrString];
- const BOOL frameChanged = !CGRectEqualToRect(_textView.frame, _view.frame);
- if (!textChanged && !frameChanged) {
+ const BOOL frameChanged = !CGRectEqualToRect(_textView.frame, _view.bounds);
+ const BOOL layoutChanged = !CGRectEqualToRect(_lastTextLayoutFrame, _view.bounds);
+ if (!textChanged && !frameChanged && !layoutChanged) {
return;
}
if (textChanged) {
@@ -142,7 +144,7 @@ using namespace facebook::react;
_suppressSelectionChange = NO;
}
if (frameChanged) {
- _textView.frame = _view.frame;
+ _textView.frame = _view.bounds;
}
__block std::vector<std::string> lines;
@@ -162,6 +164,7 @@ using namespace facebook::react;
}
}];
+ _lastTextLayoutFrame = _view.bounds;
if (_eventEmitter != nullptr) {
std::dynamic_pointer_cast<const facebook::react::RNUITextViewEventEmitter>(_eventEmitter)
->onTextLayout(facebook::react::RNUITextViewEventEmitter::OnTextLayout{static_cast<int>(self.tag), lines});