-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Add tag muted-text BaseHTMLEngineProvider to render html errors #5550
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
Conversation
When we get have an html error to display, we can wrap the error in <muted-text> to make it have our 'mutedTextLabel' styling.
src/libs/actions/BankAccounts.js
Outdated
@@ -751,7 +753,8 @@ function setupWithdrawalAccount(data) { | |||
} | |||
} else { | |||
if (response.jsonCode === 666 || response.jsonCode === 404) { | |||
error = response.message; | |||
error = response.message || response.htmlMessage; |
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 am not sure I understand this change? In general we prefer the HTML message first (on OldDot)
src/libs/actions/BankAccounts.js
Outdated
function showBankAccountErrorModal(errorModalMessage = null) { | ||
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {isErrorModalVisible: true, errorModalMessage}); | ||
function showBankAccountErrorModal(errorModalMessage = null, isErrorModalMessageHtml = false) { | ||
Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {isErrorModalVisible: true, errorModalMessage, isErrorModalMessageHtml}); |
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.
Just to confirm here, if we call merge
the value of isErrorModalMessageHtml
will be overwritten right?
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 understand that is the case
@@ -231,6 +235,7 @@ const renderers = { | |||
code: CodeRenderer, | |||
img: ImgRenderer, | |||
edited: withLocalize(EditedRenderer), | |||
'muted-text': TNodeChildrenRenderer, |
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.
Just so I'm clear on why we are doing this, please correct me if I'm wrong...
From reading about it, I think a TNodeChildrenRenderer
element is designed so it will render ONLY that element and its children when some data within the TNodeChildrenRenderer
element changes. This prevents us from re-rendering a bunch of things unnecessarily. Is that correct?
Also, when we use it, why are we nesting it inside a <RenderHTML
rather than a <Text
?
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.
About TNodeChildrenRenderer
... I actually didn't read the documentation about it, I just saw other usages like here:
App/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js
Lines 69 to 111 in e3e02c9
function AnchorRenderer({tnode, key, style}) { | |
const htmlAttribs = tnode.attributes; | |
// An auth token is needed to download Expensify chat attachments | |
const isAttachment = Boolean(htmlAttribs['data-expensify-source']); | |
const fileName = lodashGet(tnode, 'domNode.children[0].data', ''); | |
const parentStyle = lodashGet(tnode, 'parent.styles.nativeTextRet', {}); | |
const internalExpensifyPath = (htmlAttribs.href.startsWith(CONST.NEW_EXPENSIFY_URL) && htmlAttribs.href.replace(CONST.NEW_EXPENSIFY_URL, '')) | |
|| (htmlAttribs.href.startsWith(CONST.STAGING_NEW_EXPENSIFY_URL) && htmlAttribs.href.replace(CONST.STAGING_NEW_EXPENSIFY_URL, '')); | |
// If we are handling a New Expensify link then we will assume this should be opened by the app internally. This ensures that the links are opened internally via react-navigation | |
// instead of in a new tab or with a page refresh (which is the default behavior of an anchor tag) | |
if (internalExpensifyPath) { | |
return ( | |
<Text | |
style={styles.link} | |
onPress={() => Navigation.navigate(internalExpensifyPath)} | |
> | |
<TNodeChildrenRenderer tnode={tnode} /> | |
</Text> | |
); | |
} | |
return ( | |
<AnchorForCommentsOnly | |
href={htmlAttribs.href} | |
isAuthTokenRequired={isAttachment} | |
// Unless otherwise specified open all links in | |
// a new window. On Desktop this means that we will | |
// skip the default Save As... download prompt | |
// and defer to whatever browser the user has. | |
// eslint-disable-next-line react/jsx-props-no-multi-spaces | |
target={htmlAttribs.target || '_blank'} | |
rel={htmlAttribs.rel || 'noopener noreferrer'} | |
style={{...style, ...parentStyle}} | |
key={key} | |
fileName={fileName} | |
> | |
<TNodeChildrenRenderer tnode={tnode} /> | |
</AnchorForCommentsOnly> | |
); | |
} |
I just needed something that rendered the rest of the html as it would by default, but allowed me to use the react native styles mutedTextLabel
. I did the test of removing 'muted-text': TNodeChildrenRenderer,
and it works the same, seems like it is not doing anything useful.
The code
'muted-text': defaultHTMLElementModels.p.extend({
tagName: 'muted-text',
mixedUAStyles: styles.mutedTextLabel,
}),
I would expect is would make the element muted-text
render as a <p>
with our mutedTextLabel
styles, but in reality this is rendering it as a <div>
.
Using defaultHTMLElementModels.div.extend
broke the layout, that's why I ended up using p
, which for me made sense as a parent element of a message.
I'll do some testing on an Android device to confirm this is not working only in web.
Also, when we use it, why are we nesting it inside a <RenderHTML rather than a <Text?
Because the <Text
doesn't render html
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 did the test of removing 'muted-text': TNodeChildrenRenderer, and it works the same, seems like it is not doing anything useful.
Yeah...if it is not doing anything then lets get rid of it.
The miss-aligned "here" link in the error comes from using a App/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly/index.native.js Lines 39 to 60 in 56374e8
We end up using this pressable because any anchor App/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js Lines 92 to 110 in 56374e8
App/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js Lines 229 to 231 in 56374e8
Possible solutions I see:
|
I see that the miss-aligned link is also happening in the chat for Android: I'll try to do this
And fixing the miss-aligned |
In our HTMLEngineProvider, we are always handling <a> tags using AnchorRenderer. This renderer will always end up using AnchorForCommentsOnly if the href of the <a> is not an internal link. We should not use AnchorForCommentsOnly if this <a> is not within the context of a comment in a chat.
Update: to avoid using
Result: Update: well, thinking a bit more about this, it doesn't feel so right that the |
The miss-alignment link issue was reported here already: #5319 Chatted with @MitchExpensify about it, we will create a new clean GH issue. If this PR goes through, the only miss alignment remaining will be in links sent on the chat. |
To make it more consistent with <muted-text> tag solution, I added a <comment> tag to be able to recognize we are rendering a link within a comment. RenderHtml doesn't know about comments again.
Sorry, closed by mistake... Update: Refactored detection of link in comment To make it more consistent with tag solution, RenderHtml doesn't know about comments again. |
Update: Resolved conflicts. |
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.
Lookin' good Aldo. Ignore my single 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.
Tested on web and this LGTM. I noticed that if you click the error message link on the mobile app, you are taken to the sign-in screen on mobile web for OldDot and after signing in the redirect doesn't happen. I don't think that is part of this PR/issue, but just mentioning it in case.
@flodnv friendly review reminder :) |
Sorry about that, I did not intend to be a reviewer here. Feel free to merge if all is well! |
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
🚀 Deployed to production by @roryabraham in version: 1.1.8-9 🚀
|
Details
The new error text:
Comes from
Web-Secure
backend and contains a link, so I'll be sending it using HTML. See related Web-Secure PRAdded new tag
muted-text
in BaseHTMLEngineProvider, this tag is only for setting the stylemutedTextLabel
when we find the tag. The idea is that if we receive an html error from the back, we wrap it in<muted-text>
and render it usingRenderHTML
.Also, we currently render all
<a>
with external urls inhref
asAnchorForCommentsOnly
. I introduced a custom tag<comment>
to wrap comment's html, and use it to detect if we are rendering a<a>
within a comment or not. If we are rendering a<a>
outside of a comment, like the error coming from the back end, we render it using a<Text>
becauseAnchorForCommentsOnly
:Fixed Issues
$ #5626
https://github.com/Expensify/Expensify/issues/177017
Tests / QA
Dev: make sure you have the changes from this PR in you workspace
Settings > Account > Payments > Add Verified Bank Account
Routing Number: 011401533
andAccount number: 1111222233331111
QA Steps
Tested On
Screenshots
Web
Mobile Web
Desktop
iOS
Android