Support textDecorationLine on <Text> components (#709)#1056
Support textDecorationLine on <Text> components (#709)#1056matthargett merged 17 commits intomasterfrom unknown repository
Conversation
| /// Text is both Underlined and Stroke out. | ||
| /// </summary> | ||
| [EnumMember(Value = "underline line-through")] | ||
| UnderlineLineThrough |
There was a problem hiding this comment.
This is cool, this is compatible with the existing EnumHelpers class? We should re-write all the other enums to use this where possible. Ideally we could get rid of that reflection hack.
There was a problem hiding this comment.
We actually don't need this enum, you can just as easily switch case on the string itself.
In reply to: 104831419 [](ancestors = 104831419)
There was a problem hiding this comment.
That will avoid the dependency on System.Runtime.Serialization, and avoid the reflection driven changes to EnumHelpers
In reply to: 104832645 [](ancestors = 104832645,104831419)
There was a problem hiding this comment.
I personally vote for enum instead of string, if there is a limited number of variants, because it
makes corresponding code strongly-typed.
There was a problem hiding this comment.
While I tend to agree that strong typing is usually good, I don't like that we have to add yet another dependency and pay an attribute reflection penalty for all enums across the framework just to support this strong typing.
In reply to: 105130501 [](ancestors = 105130501)
There was a problem hiding this comment.
When making decision on changing EnumHelpers I was looking onto "textAlign". Logically it is same as "textDecorationLine" and they both should be treated in same way. But "textDecorationLine" contains single value with space in it, which makes it impossible to use existing approach. So, either it must be an exceptional enum, treated differently (How many such enums can we possibly have?) or the approach should be changed. I've chosen the latter.
I am not against "switch" so if you insist, that's ok. But, please note, Reflection does not have "that" bad impact on performance if it happens once. Yes, if we have 100 000 of enums, then we will see the difference, but currently we have ~20 total and maybe it will grow up to 100 or 200 at most.
| var enumMemberAttribute = type.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true).SingleOrDefault(); | ||
| if (enumMemberAttribute != null) | ||
| { | ||
| result.Add(Normalize(((EnumMemberAttribute)enumMemberAttribute).Value), value); |
There was a problem hiding this comment.
EnumMemberAttribute [](start = 43, length = 19)
Just curious, does the serialization behavior of EnumMemberAttribute only work in one direction? I.e., is the value only used to serialize to string, or is there some tool that can be used for parsing as well?
There was a problem hiding this comment.
It works both ways. For example,
Newtonsoft.Json.JsonConvert.SerializeObject(TextDecorationLine.UnderlineLineThrough, new StringEnumConverter())
will respect the EnumMemberAttribute (notice the StringEnumConverter. Without it, enum is serialized as int)
| result.Add(Normalize(name), value); | ||
|
|
||
| var enumMemberAttribute = type.GetField(name).GetCustomAttributes(typeof(EnumMemberAttribute), true).SingleOrDefault(); | ||
| if (enumMemberAttribute != null) |
There was a problem hiding this comment.
It's unfortunate that we now have to pay a reflection penalty for all other enums where this does not exist. I know this only occurs once, but its a potential performance hit nonetheless.
There was a problem hiding this comment.
That's true that Reflection brings in an overhead, but in this case, due to the fact that this method is called only once per enum, I think it's too small to have a significant impact on performance.
| /// </summary> | ||
| /// /// <param name="view">The view.</param> | ||
| /// <param name="textDecorationLineValue">The TextDecorationLine value.</param> | ||
| [ReactProp(ViewProps.TextDecorationLine)] |
There was a problem hiding this comment.
SetTextDecorationLine [](start = 20, length = 21)
I think it would be better to ignore this prop for now than to provide an incomplete implementation. The textDecorationLine should be applicable to virtual text nodes (i.e., those that correspond to the inline instances as well).
There was a problem hiding this comment.
Rolled back
|
|
||
| /// <summary> | ||
| /// Sets the TextDecorationLine for the node. | ||
| /// </summary> |
There was a problem hiding this comment.
TextDecorationLine [](start = 54, length = 18)
autodocs do not have great grammar.
There was a problem hiding this comment.
This is a case where I wish we could leave the tag empty since the argument name is self-documenting.
There was a problem hiding this comment.
Agree with @matthargett. I've just tried to have autodocs style seem like other similar properties, like FontStyle and LineHeight
| textBlock.FontStyle = _fontStyle ?? new FontStyle(); | ||
| textBlock.FontWeight = _fontWeight ?? FontWeights.Normal; | ||
| textBlock.TextDecorations = new TextDecorationCollection(TextDecorationCollection); | ||
|
|
There was a problem hiding this comment.
Again, this only solves the problem at the root level of the text node. React Native supports text decoration on the inlines / virtual text nodes.
There was a problem hiding this comment.
I can be wrong, but from what I see, node is the lowest-level possible for creating styled text components. I cannot see a way to apply a style to a raw text. It would be great if you can come up with any example to understand the problem.
There was a problem hiding this comment.
This would be supported on Android and iOS:
<Text>
Here is some regular text <Text style={{textDecorationLine: 'underline'}}>and here is some underlined virtual text</Text>.
</Text>
However, this scenario would not supported by this PR.
There was a problem hiding this comment.
Nice one. Didn't even got in mind to try this. I'll check how can I implement it this way
There was a problem hiding this comment.
My guess would be you may need to create virtual node types and control all this by checking for presence of the prop in JavaScript. I.e., in JavaScript, you might check:
if (this.props.textDecorationLine === 'underline') {
this.props.children = (<UnderlinedText>{this.props.children}</UnderlinedText>);
}
or something along these lines. I'm sure my syntax is a bit off.
|
🕐 |
This reverts commit 5de9c8e. # Conflicts: # ReactWindows/ReactNative/Views/Text/ReactTextViewManager.cs
|
Closing and reopening to trigger CLA bot |
|
@ymusiychuk-lohika, |
…anager, support decoration of inlines
|
I've put TextDecorationLine logic into ReactTextViewManager and ReactSpanViewManager. Now it supports inline decoration. |
Codecov Report
@@ Coverage Diff @@
## master #1056 +/- ##
==========================================
- Coverage 31.68% 31.62% -0.07%
==========================================
Files 253 253
Lines 17976 18013 +37
Branches 1507 1513 +6
==========================================
Hits 5696 5696
- Misses 12126 12163 +37
Partials 154 154
Continue to review full report at Codecov.
|
WPF supports both Underline and Strike-through
UWP supports only Underline. The idea behind this approach was to add an Underline directly to a Paragraph of RichTextBlock, because we know that there is always one Paragraph and thus there should be at most one Underline.