Skip to content
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

fix: parse deep link correctly #573

Merged
merged 3 commits into from
Sep 11, 2023

Conversation

Antasel
Copy link
Contributor

@Antasel Antasel commented Sep 6, 2023

Fixed Issues

$ Expensify/App#16762
Proposal: Expensify/App#16762 (comment)

Tests

Go to a chat and send following test strings and verify that urls and emails are parsed as expected.

Test Strings
[email protected] https://www.expensify.com
[email protected]://www.expensify.com
[email protected]/https://www.expensify.com
[email protected]?https://www.expensify.com
[email protected]>https://www.expensify.com
https://staging.new.expensify.com/details/[email protected]
staging.new.expensify.com/details
https://www.expensify.com?name=test&[email protected]
https://staging.new.expensify.com/[email protected]
staging.new.expensify.com/[email protected]
http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled
-https://www.expensify.com /https://www.expensify.com @https://www.expensify.com
expensify.com -expensify.com @expensify.com
https//www.expensify.com
//www.expensify.com?name=test&[email protected]
//staging.new.expensify.com/[email protected]
/[email protected]
?name=test&[email protected]
example.com/https://www.expensify.com
[email protected] staging.new.expensify.com/[email protected]&redirectUrl=https://google.com
[email protected] //staging.new.expensify.com/[email protected]&redirectUrl=https://google.com
[email protected]://staging.new.expensify.com/[email protected]&redirectUrl=https://google.com

[email protected]/https://example.com/[email protected][email protected]
[email protected]/[email protected]/https://example.com/[email protected][email protected]

Demo Video:

Screencast.from.6-9-23.09.04.20.webm

Autotest cases:

ExpensiMark-HTML-test.js new tests
test('Test urls autolinks correctly', () => {
    let testString = '[email protected] https://www.expensify.com\n' +
    '[email protected]://www.expensify.com\n' +
    '[email protected]/https://www.expensify.com\n' +
    '[email protected]?https://www.expensify.com\n' +
    '[email protected]>https://www.expensify.com\n' +
    'https://staging.new.expensify.com/details/[email protected]\n' +
    'staging.new.expensify.com/details\n\n' +
    'https://www.expensify.com?name=test&[email protected]\n' +
    'https://staging.new.expensify.com/[email protected]\n' +
    'staging.new.expensify.com/[email protected]\n' +
    'http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled\n' +
    '-https://www.expensify.com /https://www.expensify.com @https://www.expensify.com\n' +
    'expensify.com -expensify.com @expensify.com\n' +
    'https//www.expensify.com\n' +
    '//www.expensify.com?name=test&[email protected]\n' +
    '//staging.new.expensify.com/[email protected]\n' +
    '/[email protected]\n' +
    '?name=test&[email protected]\n\n' +
    'example.com/https://www.expensify.com\n' +
    '[email protected] staging.new.expensify.com/[email protected]&redirectUrl=https://google.com\n' +
    '[email protected] //staging.new.expensify.com/[email protected]&redirectUrl=https://google.com\n' +
    '[email protected]://staging.new.expensify.com/[email protected]&redirectUrl=https://google.com\n' +
    '[email protected]/https://example.com/[email protected][email protected]\n' +
    '[email protected]/[email protected]/https://example.com/[email protected][email protected]';

    let resultString = '<a href="mailto:[email protected]">[email protected]</a> <a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a><br />' + 
    '<a href="mailto:[email protected]">[email protected]</a>-<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a><br />' +
    '<a href="mailto:[email protected]">[email protected]</a>/<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a><br />' +
    '<a href="mailto:[email protected]">[email protected]</a>?<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a><br />' + 
    '<a href="mailto:[email protected]">[email protected]</a>&gt;<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a><br />' +
    '<a href="https://staging.new.expensify.com/details/[email protected]" target="_blank" rel="noreferrer noopener">https://staging.new.expensify.com/details/[email protected]</a><br />' +
    '<a href="https://staging.new.expensify.com/details" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/details</a><br /><br />'+ 
    '<a href="https://www.expensify.com?name=test&amp;[email protected]" target="_blank" rel="noreferrer noopener">https://www.expensify.com?name=test&amp;[email protected]</a><br />' +
    '<a href="https://staging.new.expensify.com/[email protected]" target="_blank" rel="noreferrer noopener">https://staging.new.expensify.com/[email protected]</a><br />' +
    '<a href="https://staging.new.expensify.com/[email protected]" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]</a><br />' +
    '<a href="http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled" target="_blank" rel="noreferrer noopener">http://necolas.github.io/react-native-web/docs/?path=/docs/components-pressable--disabled</a><br />' +
    '-<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a> /<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a> @https://www.expensify.com<br />' +
    '<a href="https://expensify.com" target="_blank" rel="noreferrer noopener">expensify.com</a> -<a href="https://expensify.com" target="_blank" rel="noreferrer noopener">expensify.com</a> @expensify.com<br />' +
    'https//<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">www.expensify.com</a><br />' +
    '//<a href="https://www.expensify.com?name=test&amp;[email protected]" target="_blank" rel="noreferrer noopener">www.expensify.com?name=test&amp;[email protected]</a><br />' +
    '//<a href="https://staging.new.expensify.com/[email protected]" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]</a><br />' +
    '/details?login=<a href="mailto:[email protected]">[email protected]</a><br />' +
    '?name=test&amp;email=<a href="mailto:[email protected]">[email protected]</a><br /><br />' +
    '<a href="https://example.com/https://www.expensify.com" target="_blank" rel="noreferrer noopener">example.com/https://www.expensify.com</a><br />' +
    '<a href="mailto:[email protected]">[email protected]</a> <a href="https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com</a><br />' +
    '<a href="mailto:[email protected]">[email protected]</a> //<a href="https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com</a><br />' +
    '<a href="mailto:[email protected]">[email protected]</a>-<a href="https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com" target="_blank" rel="noreferrer noopener">https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com</a><br />' +
    '<a href="mailto:[email protected]\">[email protected]</a>/<a href="https://example.com/[email protected][email protected]" target="_blank" rel="noreferrer noopener">https://example.com/[email protected][email protected]</a><br />' +
    '<a href="mailto:[email protected]">[email protected]</a>/<a href="mailto:[email protected]">[email protected]</a>/<a href="https://example.com/[email protected][email protected]" target="_blank" rel="noreferrer noopener">https://example.com/[email protected][email protected]</a>';
    expect(parser.replace(testString)).toBe(resultString);
});

@Antasel Antasel requested a review from a team as a code owner September 6, 2023 15:09
@melvin-bot melvin-bot bot requested review from cead22 and removed request for a team September 6, 2023 15:10
Copy link
Contributor

@0xmiros 0xmiros left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! @johnmlee101 all yours!

Automated tests pass!

app.test.mov
diff.mov

@@ -476,9 +470,28 @@ export default class ExpensiMark {
}
replacedText = replacedText.concat(textToCheck.substr(startIndex, (match.index - startIndex)));

// we want to avoid matching email address domains
Copy link
Contributor

@cead22 cead22 Sep 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// we want to avoid matching email address domains
// We want to avoid matching domains in email addresses so we don't render them as URLs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's from old PR, I just moved it to other line. but new comment is more readable.

@@ -476,9 +470,28 @@ export default class ExpensiMark {
}
replacedText = replacedText.concat(textToCheck.substr(startIndex, (match.index - startIndex)));

// we want to avoid matching email address domains
let abort = false;
let shouldRetryByAtSign = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "by at sign" mean? are we doing another try by removing the @ sign, by adding the @ sign, or by testing against a new regex with/out @ sign?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also feeling that variable name is not reasonable.

I think isReparsedByAutolink is more readable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you think about new one?

Comment on lines 481 to 483
// e.g. [email protected]/https://www.test.com
// If the matched string faces @ sign before it,
// We will retry to apply autolink rule to the string(e.g. /https://www.test.com) except for domain(e.g. expensify.com) after @ sign.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you update this comment to make it clearer?

  • What is the e.g. an example of? shouldn't that be after another comment?
  • What does "faces @ sign before it"? I suggest "If the matches string has a leading @ sign" -- use "leading" or "trailing" depending on the case
  • It should say "why"

Copy link
Contributor Author

@Antasel Antasel Sep 6, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the e.g. an example of? shouldn't that be after another comment?

yes, it's example of comment. It should be after comment normally, but I tended to point '/https://www.test.com' and '[email protected]' in comment details

What does "faces @ sign before it"? I suggest "If the matches string has a leading @ sign" -- use "leading" or "trailing" depending on the case

Your suggestion is good, I will change comment as you recommended. "if the matched string has a leading @ sign"

It should say "why"

By a Old PR, if matched string has leading @ sign, It simply aborts to apply autolink rule. But we have edge cases like [email protected]/https://www.test.com, where https://www.test.com should be parsed as url.
To explain above reason, I added a example of edge test string.

As a result, I will change comment as following:

// If the matched Url has a leading @ sign, The Url's domain can be domain of email address.
// At this case, The matched string should not be parsed as Url, 
 // but it can contain another Url which should be parsed. (e.g. [email protected]/https://www.test.com)
// So We will retry to apply autolink rule to the string(e.g. /https://www.test.com) except for domain(e.g. expensify.com) after @ sign.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Friendly reminder, your thoughts ?

shouldRetryByAtSign = true;
replacedText = replacedText.concat(domainMatch[1] + this.replace(domainMatch[3], {filterRules: ['autolink']}));
} else {
abort = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to add a comment explaining why we're setting abort to true here? It's not immediately obvious to me

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

This comment is to say why we are setting abort to true

@@ -609,6 +609,60 @@ test('Test a url ending with a closing parentheses autolinks correctly', () => {
expect(parser.replace(testString)).toBe(resultString);
});

test('Test urls autolinks correctly', () => {
let testString = '[email protected] https://www.expensify.com\n' +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little hard to read and review, so I was thinking maybe we should add a test for each of these cases, but I think a better idea would be to make this an array with entries for each case, and I think even better would be an array of arrays, where the test string and the expected string are next to each other for easy comparison, readability, review, and updates.

If you agree, can you update accordingly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about dividing it into 3~4 test sections according to test string type, like Expensify/App#16762 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That works, but I still arrays are better than string concats, and an array of array such that the test and expected strings are next to each other is better than both

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following implementation is acceptable ?

    const testCases = [
        {
            testString: '[email protected] https://www.expensify.com',
            resultString: '<a href="mailto:[email protected]">[email protected]</a> <a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a>',
        },
        {
            testString: '[email protected]://www.expensify.com',
            resultString: '<a href="mailto:[email protected]">[email protected]</a>-<a href="https://www.expensify.com" target="_blank" rel="noreferrer noopener">https://www.expensify.com</a>',
        },
    ];

    testCases.forEach(testCase => {
        expect(parser.replace(testCase.testString)).toBe(testCase.resultString);
    });

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that looks better than what I had in mind :)

@Antasel
Copy link
Contributor Author

Antasel commented Sep 7, 2023

@cead22 Could you please check new commit 8bc8591?

},
{
testString: 'expensify.com -expensify.com @expensify.com',
resultString: '<a href="https://expensify.com" target="_blank" rel="noreferrer noopener">expensify.com</a> -<a href="https://expensify.com" target="_blank" rel="noreferrer noopener">expensify.com</a> @expensify.com',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a blocker, and it's not specific to this test case, but I'm wondering if we should use :// instead of https://, in case there are sites that don't support https so we don't end up rendering broken links

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't check https:// in the test case, you were about to point other cases ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean. What I was wondering was wether the result string should be <a href="https://expensify.com/"... or <a href="://expensify.com/"... which would use whatever protocol is already being used.

This is related to my comment here, but we can keep this as is for now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes. <a href="https://expensify.com/"... . is being used

},
{
testString: '//www.expensify.com?name=test&[email protected]',
resultString: '//<a href="https://www.expensify.com?name=test&amp;[email protected]" target="_blank" rel="noreferrer noopener">www.expensify.com?name=test&amp;[email protected]</a>',

This comment was marked as resolved.

resultString: '//<a href="https://www.expensify.com?name=test&amp;[email protected]" target="_blank" rel="noreferrer noopener">www.expensify.com?name=test&amp;[email protected]</a>',
},
{
testString: '//staging.new.expensify.com/[email protected]',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a test case for a string that starts with :// like ://staging.new.expensify.com/[email protected] and ensure that renders a link?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think :// should be part of link unless it has http or https as prefix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean that we need the following test case instead of with // ?

{
            testString: '://staging.new.expensify.com/[email protected]',
            resultString: '://<a href="https://staging.new.expensify.com/[email protected]" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]</a>',
        },

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this is my old school thinking, but on browsers, a link like ://expensify.com translates into https://expensify.com if the protocol being used on that page is https, and to http://expensify.com is the protocol is http. That's what made me think we should parse ://expensify.com as a URL, but maybe we don't need to do that, just wanted to get more thoughts.

This isn't a blocker

},
{
testString: 'https://www.expensify.com?name=test&[email protected]',
resultString: '<a href="https://www.expensify.com?name=test&amp;[email protected]" target="_blank" rel="noreferrer noopener">https://www.expensify.com?name=test&amp;[email protected]</a>',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks wrong, since &amp; shouldn't be present in an href, this is only for HTML content

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'ts from old PR, and we have other test cases to write it in html attribute.
I think &amp: should be present there.
https://stackoverflow.com/questions/3705591/do-i-encode-ampersands-in-a-href

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is out of scope for this PR. All resultString in test cases converts & to &amp; (not only changes from this PR)
And this is actually decoded again:

Screenshot 2023-09-07 at 10 13 41 PM

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice thanks for sharing that! TIL you can and should html-encode & signs in html attributes

},
{
testString: '[email protected] //staging.new.expensify.com/[email protected]&redirectUrl=https://google.com',
resultString: '<a href="mailto:[email protected]">[email protected]</a> //<a href="https://staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com" target="_blank" rel="noreferrer noopener">staging.new.expensify.com/[email protected]&amp;redirectUrl=https://google.com</a>',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be URL-encoding @ signs as %40? I thought it was weird to have explicit @ signs in URLs at first and testing this testString on slack, I noticed it renders something very different which isn't related to this, but made me wonder again

Copy link
Contributor Author

@Antasel Antasel Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Screenshot_1

On discord, we have explicit @ signs in Urls,
and on this Github platform as well

Comment on lines 473 to 494
// We want to avoid matching domains in email addresses so we don't render them as URLs.
// If the matched Url has a leading @ sign, The Url's domain can be a domain of email address.
// At this case, The matched string should not be parsed as Url,
// But it can contain another Url which should be parsed. (e.g. [email protected]/https://www.test.com)
// So We will retry to apply autolink rule to the string(e.g. /https://www.test.com) except for domain(e.g. expensify.com) after @ sign.
let abort = false;
let isReparsedByAutolink = false;

if ((match.index !== 0) && (textToCheck[match.index - 1] === '@')) {
const domainRegex = new RegExp('^(([a-z-0-9]+\\.)+[a-z]{2,})(\\S*)', 'i');
const domainMatch = domainRegex.exec(match[2]);

if ((domainMatch !== null) && (domainMatch[3] !== '')) {
isReparsedByAutolink = true;
replacedText = replacedText.concat(domainMatch[1] + this.replace(domainMatch[3], {filterRules: ['autolink']}));
} else {
abort = true;
}
}

if (abort || match[1].includes('<pre>')) {
replacedText = replacedText.concat(textToCheck.substr(match.index, (match[0].length)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is still hard to understand, so here's a suggestion to make things clearer, but I'm not sure if what I'm saying in the comments, or if the updated variable names are accurate, so I could use your help

            // We want to avoid matching domains in email addresses so we don't render them as URLs,
            // but we need to check if there are valid URLs after the email address and render them accordingly,
            // e.g. [email protected]/https://www.test.com
            let isDoneMatching = false;
            let shouldApplyAutoLinkAgain = true;

            // If we find a URL with a leading @ sign, we need look for other domains in the rest of the string
            if ((match.index !== 0) && (textToCheck[match.index - 1] === '@')) {
                const domainRegex = new RegExp('^(([a-z-0-9]+\\.)+[a-z]{2,})(\\S*)', 'i');
                const domainMatch = domainRegex.exec(match[2]);

                // If we find another domain, we apply the auto link rule again and set a flag to avoid doing it
                if ((domainMatch !== null) && (domainMatch[3] !== '')) {
                    replacedText = replacedText.concat(domainMatch[1] + this.replace(domainMatch[3], {filterRules: ['autolink']}));
                    shouldApplyAutoLinkAgain = false;
                } else {
                    // Otherwise, we're done applying rules
                    isDoneMatching = true;
                }
            }

            // Here we should probably explain in words what the code is doing, why, and what the condition means
            if (isDoneMatching || match[1].includes('<pre>')) {
                replacedText = replacedText.concat(textToCheck.substr(match.index, (match[0].length)));
            } else if (shouldApplyAutoLinkAgain) {

Copy link
Contributor Author

@Antasel Antasel Sep 7, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// Here we should probably explain in words what the code is doing, why, and what the condition means

it's out of scope for this PR.

// If we find a URL with a leading @ sign, we need look for other domains in the rest of the string

If we find a URL with a leading @ sign, we need look for other valid URL in the rest of the string.

// If we find another domain, we apply the auto link rule again and set a flag to avoid doing it

If we find another string trailing domain, we apply the auto link rule again and set a flag to avoid doing it

@cead22 I amended something on your comment, I think it's more accurate to explain

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's out of scope for this PR.

I understand you didn't write this in this PR, but we usually improve code around the code we're editing as we go, and given this isn't super clear, I think we should update it in this PR

If we find a URL with a leading @ sign, we need look for other valid URL in the rest of the string.

Small correction: If we find a URL with a leading @ sign, we need to look for other valid URLs in the rest of the string.

If we find another string trailing domain, we apply the auto link rule again and set a flag to avoid doing it

I don't think "string trailing domain" makes sense, how about

If we find another domain in the remainder of the string, we apply the auto link rule again and set a flag to avoid re-doing below

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand you didn't write this in this PR, but we usually improve code around the code we're editing as we go, and given this isn't super clear, I think we should update it in this PR

for the condition match[1].includes('<pre>'), we can comment like below.

// We don't want to apply link rule if match[1] contains the code block inside the [] of the markdown e.g. [```example```](https://example.com)

other conditions's flags are already explained.
What the codes do can be figured out without comments, first one is to concatenate string without applying rule, second one is to apply rule

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we find another domain in the remainder of the string, we apply the auto link rule again and set a flag to avoid re-doing below

it's good

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 👍

@0xmiros
Copy link
Contributor

0xmiros commented Sep 8, 2023

@cead22 thanks for the thorough reviews.
@Antasel anything pending before final review?

@Antasel
Copy link
Contributor Author

Antasel commented Sep 8, 2023

@Antasel anything pending before final review?

I was waiting for @cead22 's confirmation

@cead22 Thanks for your review.
Please check new commit

@cead22
Copy link
Contributor

cead22 commented Sep 8, 2023

@0xmiroslav wanna give a final review on the latest update before we merge?

@0xmiros
Copy link
Contributor

0xmiros commented Sep 8, 2023

@0xmiroslav wanna give a final review on the latest update before we merge?

reviewed and retested. all good to merge.
But maybe merge freeze will be applied to this repo as well?

@cead22
Copy link
Contributor

cead22 commented Sep 11, 2023

Thank you! The freeze would apply, but it's over now :)
image

@cead22 cead22 merged commit 191c0c8 into Expensify:main Sep 11, 2023
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants