-
Notifications
You must be signed in to change notification settings - Fork 95
[iOS & Android] Enable borderRadius in all mention types #720
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[iOS & Android] Enable borderRadius in all mention types #720
Conversation
…s to all mentions
apple/MarkdownTextLayoutFragment.mm
Outdated
| CGFloat marginLeft = _markdownUtils.markdownStyle.blockquoteMarginLeft; | ||
| CGFloat borderWidth = _markdownUtils.markdownStyle.blockquoteBorderWidth; | ||
| CGFloat paddingLeft = _markdownUtils.markdownStyle.blockquotePaddingLeft; | ||
| CGFloat shift = marginLeft + borderWidth + paddingLeft; | ||
|
|
||
| fragmentTextBounds.origin.x -= (paddingLeft + borderWidth) + shift * ([_depth unsignedIntValue] - 1); | ||
| fragmentTextBounds.size.width = borderWidth + shift * ([_depth unsignedIntValue] - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the blockquote logic is now duplicated, can we somehow dedupe it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was already :/
I could create a helper function to get the shift to make it look better but the logic would stay unchanged
I think we need it to be that way because boundingRect is also used in renderingSurfaceBounds
…e` to a separate file
android/src/main/java/com/expensify/livemarkdown/spans/MarkdownBackgroundSpan.java
Outdated
Show resolved
Hide resolved
|
I fixed last known iOS issue in this commit - 28b6a13 |
jmusial
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dunno if those are connected to this PR, or just existing bugs. In all cases, it's just on mobile devices
- android, switching to single line breaks highlights :(
Screen.Recording.2025-08-22.at.13.04.20.mov
- android, Cursor not visible when within
codeblockormention
Screen.Recording.2025-08-22.at.13.08.38.mov
|
Na ios dzieją się rzeczy niestworzone :( Ale to też single - line to jest Simulator.Screen.Recording.-.iPhone.15.Pro.-.2025-08-22.at.14.34.03.mp4 |
We can try to fix it in a separate PR but I think we need to consult with the design team. I'll leave it as an open idea because it's not in the scope of this PR Thanks for noticing! |
For the context, this was discussed on Slack: https://swmansion.slack.com/archives/C01GTK53T8Q/p1755699466781499 |
| NSTextStorage *textStorage = [_textField valueForKey:@"_textStorage"]; | ||
| NSTextContainer *textContainer = [_textField valueForKey:@"_textContainer"]; | ||
| NSTextLayoutManager *textLayoutManager = [textContainer valueForKey:@"_textLayoutManager"]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if accessing UITextField's private fields could cause some rejections on app store. We should probably verify that
cc @tomekzaw any ideas on how to do that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to obfuscate all the selectors here, e.g. "_text" + "tuoyal".reversed() + Manager"
|
@tomekzaw @parasharrajat @Skalakid PR's ready for review 🎉 Please review it carefully and ask me any questions because the solution is quite complicated in a few places. If you think adding comments would be valuable let me know! |
Skalakid
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, amazing work! Left some comments, but overall LGTM
| boolean mentionStarts = lineStart <= relativeMentionStart; | ||
| boolean mentionEnds = lineEnd >= relativeMentionEnd; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about renaming these variables to something for example like: startsInThisLine and endsInThisLine
| if (@available(iOS 16.0, *)) { | ||
| RCTMarkdownTextBackground *textBackground = [[RCTMarkdownTextBackground alloc] init]; | ||
| textBackground.color = markdownStyle.mentionHereBackgroundColor; | ||
| textBackground.borderRadius = markdownStyle.mentionHereBorderRadius; | ||
|
|
||
| [attributedString addAttribute:RCTLiveMarkdownTextBackgroundAttributeName | ||
| value:textBackground | ||
| range:range]; | ||
| } else { | ||
| [attributedString addAttribute:NSBackgroundColorAttributeName value:markdownStyle.mentionHereBackgroundColor range:range]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that there is a lot of similar code. How about moving it to a separate function with textColor, backgroundColor, and borderRadius as props (etc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Helper function for applying mention-related attributes sounds good!
| NSRange intersection = NSIntersectionRange(lineRange, mentionRange); | ||
| CGPoint startLocation = [lineFragment locationForCharacterAtIndex:intersection.location]; | ||
| if (isSingleline && startLocation.x == 0 && intersection.location > 0) { | ||
| // singleline: mention starts off screen, no need to draw background |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add an explanation that it happens when the input isn't focused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The amount of different start and end variables is a bit overwhelming there 😓. Maybe let's add some general comments or something?
| mPreBackgroundColor = parseColor(map, "pre", "backgroundColor", context); | ||
| mMentionHereColor = parseColor(map, "mentionHere", "color", context); | ||
| mMentionHereBackgroundColor = parseColor(map, "mentionHere", "backgroundColor", context); | ||
| mMentionHereBorderRadius = parseFloat(map, "mentionHere", "borderRadius") * screenDensity; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather keep the original value of borderRadius in MarkdownStyle and multiply it by screenDensity near the drawing logic.
|
|
||
| @property (nonnull, atomic) RCTMarkdownUtils *markdownUtils; | ||
|
|
||
| @property NSUInteger depth; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At some point we might wanna rename depth to blockquoteDepth as this is unrelated to mentions. This can be done in a separate PR (to be merged before or after this one).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd suggest moving these two classes to separate files, i.e. RCTMarkdownTextBackground.h and RCTMarkdownTextBackground.mm (and the same for RCTMarkdownTextBackgroundWithRange).



Details
This PR adds support for
borderRadiusprop in mentions styles on iOS & AndroidRelated Issues
Expensify/App#19299
Manual Tests
iOS & Android:
Linked PRs