text:
[$1000] Android - Composer input overlaps with attachment separator

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!

Action Performed:

Launch the app -> Login in account
Navigate any chat conversation
Notice composer input (from left side it overlaps)

Expected Result:
Composer input should not be overlaps with attachment separator
Actual Result:
Composer input overlaps with attachment separator
Workaround:
unknown
Platforms:

Which of our officially supported platforms is this issue occurring on?

[x] Android / native
[ ] Android / Chrome
[ ] iOS / native
[ ] iOS / Safari
[ ] MacOS / Chrome / Safari
[ ] MacOS / Desktop

Version Number: 1.2.93-4
Reproducible in staging?: y
Reproducible in production?: y
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos: Any additional supporting documentation

Expensify/Expensify Issue URL:
Issue reported by: @dhairyasenjaliya
Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1680359256103449
View all open jobs on GitHub
Upwork Automation - Do Not Edit

Upwork Job URL: https://www.upwork.com/jobs/~0160683cfa6e9f3593
Upwork Job ID: 1643312444077060096
Last Price Increase: 2023-04-04

Triggered auto assignment to @puneetlath (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

Bug0 Triage Checklist (Main S/O)

[ ] This "bug" occurs on a supported platform (ensure Platforms in OP are ✅)
[ ] This bug is not a duplicate report (check E/App issues and #expensify-bugs)

If it is, comment with a link to the original report, close the issue and add any novel details to the original issue instead

[ ] This bug is reproducible using the reproduction steps in the OP. S/O

If the reproduction steps are clear and you're unable to reproduce the bug, check with the reporter and QA first, then close the issue.
If the reproduction steps aren't clear and you determine the correct steps, please update the OP.

[ ] This issue is filled out as thoroughly and clearly as possible

Pay special attention to the title, results, platforms where the bug occurs, and if the bug happens on staging/production.

[ ] I have reviewed and subscribed to the linked Slack conversation to ensure Slack/Github stay in sync

Wow @dhairyasenjaliya you've got some good eyes.

Job added to Upwork: https://www.upwork.com/jobs/~0160683cfa6e9f3593

Current assignee @puneetlath is eligible for the External assigner, not assigning anyone new.

Proposal
Please re-state the problem that we are trying to solve in this issue.
composer input overlaps with attachment separator in android
What is the root cause of that problem?
the root case is ButtonAttachment borderRightWidth: 1 shown blurry on some screen density.
react native use dp for dimensions and round it to px, so if value 1dp = 2.5 pixels, some devices show it blurely because physical screens have only a fixed number of pixels.
to know how many pixels in 1dp  in any device use PixelRatio.get().
in my emulator 1dp = 2.5px so the last .5px show blurely.
and in the app the current style for footer is :

<ButtonAttachment style={{borderRightWidth: 1}} />
// view paddingVertical: 5, and no backgroundColor let border to show blurely
<View>
    // Composer has backgroundColor: themeColors.componentBG
    <Composer />
</View>

What changes do you think we should make in order to solve the problem?
apply the same background color for <Composer /> and <View> wrap it, or clear it from both, or set it in the wraper.
my sugguest is to add backgroundColor: themeColors.componentBG for the wraper <View> here.
and also if we found the ButtonAttachment borderRightWidth: 1 is very thin, we may increase it.
    textInputComposeSpacing: {
        paddingVertical: 5,
        ...flex.flexRow,
        flex: 1,
        backgroundColor: themeColors.componentBG,
    },

What alternative solutions did you explore? (Optional)

Proposal
Please re-state the problem that we are trying to solve in this issue.
composer input overlaps with attachment separator in android
What is the root cause of that problem?
The root case may be the fixed width provided in the styling.
What changes do you think we should make in order to solve the problem?
the issue can be solved by not providing fixed width of composer and add a bit margin to it so it could have a safe space from separator and send button

Proposal
Please re-state the problem that we are trying to solve in this issue.
composer input overlaps with attachment separator in android
What is the root cause of that problem?
The root cause of this problem is styling.
What changes do you think we should make in order to solve the problem?
This issue can be fixed by adding min-width and max-width in the massage dialog div.

@ahmedGaber93 Thanks for the proposal. I'm not sure this is blur related. If you zoom the following screenshot https://user-images.githubusercontent.com/43996225/229310637-cf6becf7-ebc5-433f-9c6d-d73181242e12.png you will see that the separator is shown correctly on top and bottom parts and only the middle part where the input is rendered it's cut (overlapped).

@Mabroorkhan Thanks for the proposal. Your RCA is not clear, you need to pinpoint the exact root cause and not guess potential causes.

@UzairHKhan Thanks for the proposal. Your RCA is not clear, can you elaborate? And why this happens on Android only?

@s77rt some time it only happens in a single platform or in similar screen size phones and works fine in all others the main cause of these types of issues is the width of the boxes if it is taking the width more than it requires it will overlap or can displace another box the possible way to fix this is by adding
 width: -webkit-fit-content;
 width: -moz-fit-content;
 width: fit-content;

This similar issue occurred in my previous work history and was happening only in iOS.

@UzairHKhan If that's the case then we need to figure out why the input is taking more space than it requires.

@s77rt I find the issue is due to flex: 4 1 0% in textArea styling which can be fixed byflex:  1 and margin: 0px 2px

@Mabroorkhan Thanks for checking. Can you elaborate with this happen only on Android?

@s77rt Yes I need to dive into the code to get more context on this possibly textarea has some width.

@s77rt I found more bugs in it

in screen width 320px the border is cutting off from the top when the placeholder is take two lines img 2
when the placeholder goes in three lines we see expend button img 2 after clicking the expend button the textarea expands and we see it like this img 3

@s77rt Another possible way to fix the border issue is to make the textarea background transparent it won't affect the UI as div also have same bg color and if the text overlaps the border it will still be visible

@s77rt i think this overlaps not related with width of any View in the component, because i trying simple example in expo snack and the overlaps is exist.

simple example code.
import * as React from 'react';
import { View } from 'react-native';

export default function App() {
  return (
    <View style={{lex: 1, height: "100%", justifyContent: 'center'}}>
      <View style={{
        borderWidth : 1,
        borderColor : "green",
        borderRadius : 15,
        overflow : 'hidden',
        flexDirection: "row",
        alignItems: "center",
      }}>
        <View style={{
          height: 30,
          width: 30,
          backgroundColor: "black",
          borderRightWidth: 1,
          borderRightColor: "green"
        }} />
        <View style={{backgroundColor: "black", flex:1, height: 20, borderWidth: 0}} />
      </View>
    </View>
  );
}

result.

you can try snack here but test it in a real device because i think emulators don't have the a real number of pixels.
and also result may be diffrent depond on sceen density.

@UzairHKhan Thanks for the proposed fix but I think we are not looking for solutions at this point. It's important to understand the root cause first.

@ahmedGaber93 Thanks for checking that. So looks like the bug is in RN. Let's fix it on RN then.

@s77rt thanks for the feed back

@s77rt I think the bug is in android itself not react native, and setting the wrapper view background is the simple way to fix the UI issue.

@ahmedGaber93 Were you able to replicate the bug on Android (native code)?

@s77rt no i couldn't replicate the bug on android (native code).

Not overdue. Still waiting for proposals, so far the bug seems to exist on RN too and we are aiming to fix it on that level (assuming the bug is not originating from native Android SDK).

📣 It's been a week! Do we have any satisfactory proposals yet? Do we need to adjust the bounty for this issue? 💸

Upwork job price has been updated to $2000

Still waiting on more proposals.

@puneetlath @s77rt this issue was created 2 weeks ago. Are we close to approving a proposal? If not, what's blocking us from getting this issue assigned? Don't hesitate to create a thread in #expensify-open-source to align faster in real time. Thanks!

We are not any close to picking a proposal. So far we think the bug is in RN and no proposals submitted for that matter.

@s77rt as I have proposed before these type of issues is caused by the width alow me solve this bug

@UzairHKhan Thanks for the follow up. I'm not really convinced this is the reason. Can you please explain why this is happening on Android only?

@s77rt in the current implementation I noticed that it is using flex: 1 to fill all the available space between but in compilation of RN some time it produces bug in single platform and work fine in other so we have to replace flex: 1 with  width and possibly it will fix the bug

Hi I'm Nicolay from Callstack - expert contributor group - will start investigation in this area

@UzairHKhan

but in compilation of RN some time it produces bug in single platform

We need to fix that bug instead of replacing flex with width.

@puneetlath Please assign @narefyev91 as per the process.

📣 @narefyev91 You have been assigned to this job by @puneetlath!
Please apply to this job in Upwork and leave a comment on the Github issue letting us know when we can expect a PR to be ready for review 🧑💻
Keep in mind: Code of Conduct | Contributing 📖

My updates - indicated an issue - found a possible solution - provide proposal for internal review. Will post here - as soon as i get approval

@narefyev91 Thanks for the proposal. So If I get this correctly, you are saying that the Composer is not overlapping with the separator. But it's actually the separator taking more space. Would that be "about" right?
If that's the case why using flex does not take into consideration that extra space taken by the separator and draw the input on that used extra space. Why the input is not shifted so it does not collide with that? Is this by design? And lastly why we are not experiencing the bug on iOS (or are we)?

@s77rt StylesSheet.hairlineWidth will be very thin because it equals 1px, but borderRightWidth: 1 equal about 2.5px or 3px in modern devices depend on PixelRatio.get() and also it may not be visible in some devices.

@narefyev91 Thanks for the proposal. So If I get this correctly, you are saying that the Composer is not overlapping with the separator. But it's actually the separator taking more space. Would that be "about" right?
If that's the case why using flex does not take into consideration that extra space taken by the separator and draw the input on that used extra space. Why the input is not shifted so it does not collide with that? Is this by design? And lastly why we are not experiencing the bug on iOS (or are we)?

I will say nothing is overlapping - we have dropping pixels in android - as you see in the screenshots. TextInput taken correct space, and the issue that line is not renders at it should be - not in a full width - that's why TextInput sees that max available space started from rendered line (rendered line it's line with bold color and not thin). Such issue does not exist on IOS because in IOS 1px = 1px - without any pixel drops.

@s77rt I think StylesSheet.hairlineWidth will be very thin because it equals 1px, but borderRightWidth: 1 equal about 2.5px or 3px in modern devices depend on PixelRatio.get() and also it may not be visible in some devices.

We already use StylesSheet.hairlineWidth under the hood - it equal already drawable line - which in bold. If it will be not visible - the whole border will be not visible as well. And 1px is not equal 2.5px or 3px to be honest - it's something around 1.6px - 1.8px in modern phones

@narefyev91 I just try it before in my real device in this snack, and it displayed very thin and not fixed the issue, but may I missed something.

@ahmedGaber93 For sure the line will be thin that's why i told that maybe make sense to apply this width for the whole component. BTW i can't really say why in expo snack it still cutting, i tested on real device and devices in emulators and that was working. In any case i provided 2 possible solutions which i discovered

@narefyev91

Such issue does not exist on IOS because in IOS 1px = 1px - without any pixel drops.

Did you mean to say that 1dp = a round number of pixels? Where on Android it may not always be the case?
Can you please include screenshots before the change and after the suggested change for both iOS and Android?

@s77rt
https://angrytools.com/android/pixelcalc/
Example

Result you can see here:
Before:

After:

@s77rt IOS does not need any changes in IOS - there are no issues with dropping pixels

Also, if we swap the text input with a simple view/rectangle, will we experience the same bug?

@s77rt
Sure:
IOS 1px (default)

IOS - calculated pixel - 1 + (1 - Stylesheet.hairlineWidth)

IOS - Stylesheet.hairlineWidth

Android - calculated pixel 1 + (1 - Stylesheet.hairlineWidth)

Android - Stylesheet.hairlineWidth

Platform specifications:
IOS, webIOS, webAndroid, Desktop, Web -  1px = 1px (standard behaviour) - should not be changed
Android - 1px = 1 + (1 - Stylesheet.hairlineWidth) - should be changed (to prevent dropping pixel)

@narefyev91 Thank you!
I have two concerns:

Are we sure the fault is not on the TextInput (not getting shifted). Check comment above.
You are suggesting to set borderRightWidth: 1 + (1 - StyleSheet.hairlineWidth) This does not make much sense because StyleSheet.hairlineWidth will return the dp value that corresponds to one pixel on the device. Example: 0.5 dp => 1 pixel. Using multiples of that value (1, 1.5, etc.) is okay as this will still result in a fixed number of pixels (2, 3, resp). But if we alter the value by addition/subtraction the new dp may correspend to a non fixed number of pixels e.g. 2.5 pixel so the OS will have to compensate and the blur effect can be seen again. I don't think we consider those as "dropping" pixels.

@puneetlath @s77rt @narefyev91 this issue is now 3 weeks old. There is one more week left before this issue breaks WAQ and will need to go internal. What needs to happen to get a PR in review this week? Please create a thread in #expensify-open-source to discuss. Thanks!

Still discussing proposals

@s77rt Hey!
For your first point:

TextInput really stays on all possible space - and will also cut a peace of attachment border
For the second point:
Not really - 1dp - will be fully different on devices - and variation of it is from 0.2 - to 0.5. For Example for devices with large screens i get between 0.28 - 0.36. On small devices - 0.4 - 0.5.

@narefyev91 Hi again :wave:  I'm not sure you answered my questions :sweat_smile:

Can you try use a <View /> with a different background instead of the TextInput and see if it actually cut the separator or not
I don't think you understood my concern in this point. I'm not talking about different devices.  In one device, the StyleSheet.hairlineWidth  will return how much dp would correspond to one pixel. Is that right? Let's assume the value for our device is 0.3 dp. So if we set the border width to 0.3 we will be sure that exactly 1 pixel will be used so the line will look clear and blur-free. Do we agree on that so far? If we set it to 0.6 we will get 2 pixels. So any multiple of 0.3 will result in a fixed number of pixels. Still makes sense? Okay, now if we apply your suggested formula 1 + (1 - StyleSheet.hairlineWidth) we will get 1.7 and this is not a multiple of 0.3 so it will result in blurry pixels (5.67 px).

@s77rt Sure thing! this is simply view with Text inside

@s77rt BTW - i came up with some maybe different solution - if we have such issues with border in android - maybe we will fully remove it? And use Separator as simple View with width 1. Which will not impact any other platform and bring same visual effect for android as well
                                    </AttachmentPicker>
                                    <View style={{width: 1, height: 'auto', backgroundColor: themeColors.border}}/>
                                    <View style={[styles.textInputComposeSpacing]}>

And we will get on android this

@narefyev91 Actually I was looking more into this and I think we still have more to explore. I think we are not seeing the blur pixels on iOS just because we are lucky :grin:.
The ratio on iOS is either 2 or 3 (based on https://reactnative.dev/docs/pixelratio#get) and those ratios plays well with a border width of pixel. I have compiled this script to help understand the results.
let analyseOptimalBorderWidth = (ratio) => {
    // Based on https://github.com/facebook/react-native/blob/4da201396c12cbfa8427d17465376de123913f62/packages/react-native/Libraries/StyleSheet/StyleSheet.js#L164-L167
    let hairlineWidth = Math.round(0.4 * ratio) / ratio;
    if (hairlineWidth === 0) {
        hairlineWidth = 1 / ratio;
    }
    [1, 1.3, 1.5, 1.8, 2, hairlineWidth].forEach(width => {
        const numPixels = width / hairlineWidth;
        const isRoundNumPixels = numPixels % 1 === 0;
        console.log(`Setting borderWidth to ${width} will use ${numPixels} pixel(s) ${isRoundNumPixels ? '✅' : '❌'}`);
    });
}

console.log("Tesing with ratio of 1 (mdpi Android devices)");
analyseOptimalBorderWidth(1);

console.log('='.repeat(30)+'\n');

console.log("Tesing with ratio of 1.5 (hdpi Android devices)");
analyseOptimalBorderWidth(1.5);

console.log('='.repeat(30)+'\n');

console.log("Tesing with ratio of 2 (xhdpi Android devices, iPhone 7, 8, 11)");
analyseOptimalBorderWidth(2);

console.log('='.repeat(30)+'\n');

console.log("Tesing with ratio of 2.5 (?)");
analyseOptimalBorderWidth(2.5);

console.log('='.repeat(30)+'\n');

console.log("Tesing with ratio of 3 (xxhdpi Android devices, iPhone 7 Plus, 8 Plus, X, XS, XS Max, 11 Pro, 11 Pro Max)");
analyseOptimalBorderWidth(3);

console.log('='.repeat(30)+'\n');

console.log("Tesing with ratio of 3.5 (xxxhdpi Android devices)");
analyseOptimalBorderWidth(3);

As you can see that on iOS a borderwidth of 1 will always use a round number of pixels. So what we should test instead is the outcome of tricky borderwidth like 1.8, this should result in a non-round number of pixels. Will iOS show some blurry pixels in that case? And if so will they overlap with the text input or not.

Tesing with ratio of 1 (mdpi Android devices)

Setting borderWidth to 1 will use 1 pixel(s) ✔
Setting borderWidth to 1.3 will use 1.3 pixel(s) ❌
Setting borderWidth to 1.5 will use 1.5 pixel(s) ❌
Setting borderWidth to 1.8 will use 1.8 pixel(s) ❌
Setting borderWidth to 2 will use 2 pixel(s) ✔
Setting borderWidth to 1 will use 1 pixel(s) ✔

Tesing with ratio of 1.5 (hdpi Android devices)

Setting borderWidth to 1 will use 1.5 pixel(s) ❌
Setting borderWidth to 1.3 will use 1.9500000000000002 pixel(s) ❌
Setting borderWidth to 1.5 will use 2.25 pixel(s) ❌
Setting borderWidth to 1.8 will use 2.7 pixel(s) ❌
Setting borderWidth to 2 will use 3 pixel(s) ✔
Setting borderWidth to 0.6666666666666666 will use 1 pixel(s) ✔

Tesing with ratio of 2 (xhdpi Android devices, iPhone 7, 8, 11)

Setting borderWidth to 1 will use 2 pixel(s) ✔
Setting borderWidth to 1.3 will use 2.6 pixel(s) ❌
Setting borderWidth to 1.5 will use 3 pixel(s) ✔
Setting borderWidth to 1.8 will use 3.6 pixel(s) ❌
Setting borderWidth to 2 will use 4 pixel(s) ✔
Setting borderWidth to 0.5 will use 1 pixel(s) ✔

Tesing with ratio of 2.5 (?)

Setting borderWidth to 1 will use 2.5 pixel(s) ❌
Setting borderWidth to 1.3 will use 3.25 pixel(s) ❌
Setting borderWidth to 1.5 will use 3.75 pixel(s) ❌
Setting borderWidth to 1.8 will use 4.5 pixel(s) ❌
Setting borderWidth to 2 will use 5 pixel(s) ✔
Setting borderWidth to 0.4 will use 1 pixel(s) ✔

Tesing with ratio of 3 (xxhdpi Android devices, iPhone 7 Plus, 8 Plus, X, XS, XS Max, 11 Pro, 11 Pro Max)

Setting borderWidth to 1 will use 3 pixel(s) ✔
Setting borderWidth to 1.3 will use 3.9000000000000004 pixel(s) ❌
Setting borderWidth to 1.5 will use 4.5 pixel(s) ❌
Setting borderWidth to 1.8 will use 5.4 pixel(s) ❌
Setting borderWidth to 2 will use 6 pixel(s) ✔
Setting borderWidth to 0.3333333333333333 will use 1 pixel(s) ✔

Tesing with ratio of 3.5 (xxxhdpi Android devices)

Setting borderWidth to 1 will use 3 pixel(s) ✔
Setting borderWidth to 1.3 will use 3.9000000000000004 pixel(s) ❌
Setting borderWidth to 1.5 will use 4.5 pixel(s) ❌
Setting borderWidth to 1.8 will use 5.4 pixel(s) ❌
Setting borderWidth to 2 will use 6 pixel(s) ✔
Setting borderWidth to 0.3333333333333333 will use 1 pixel(s)

Testing with ratio of 1 (mdpi Android devices)

Setting borderWidth to 1 will use 1 pixel(s) ✔
Setting borderWidth to 1.3 will use 1.3 pixel(s) ❌
Setting borderWidth to 1.5 will use 1.5 pixel(s) ❌
Setting borderWidth to 1.8 will use 1.8 pixel(s) ❌
Setting borderWidth to 2 will use 2 pixel(s) ✔
Setting borderWidth to 1 will use 1 pixel(s) ✔

Testing with ratio of 1.5 (hdpi Android devices)

Setting borderWidth to 1 will use 1.5 pixel(s) ❌
Setting borderWidth to 1.3 will use 1.9500000000000002 pixel(s) ❌
Setting borderWidth to 1.5 will use 2.25 pixel(s) ❌
Setting borderWidth to 1.8 will use 2.7 pixel(s) ❌
Setting borderWidth to 2 will use 3 pixel(s) ✔
Setting borderWidth to 0.6666666666666666 will use 1 pixel(s) ✔

Testing with ratio of 2 (xhdpi Android devices, iPhone 7, 8, 11)

Setting borderWidth to 1 will use 2 pixel(s) ✔
Setting borderWidth to 1.3 will use 2.6 pixel(s) ❌
Setting borderWidth to 1.5 will use 3 pixel(s) ✔
Setting borderWidth to 1.8 will use 3.6 pixel(s) ❌
Setting borderWidth to 2 will use 4 pixel(s) ✔
Setting borderWidth to 0.5 will use 1 pixel(s) ✔

Testing with ratio of 2.5 (?)

Setting borderWidth to 1 will use 2.5 pixel(s) ❌
Setting borderWidth to 1.3 will use 3.25 pixel(s) ❌
Setting borderWidth to 1.5 will use 3.75 pixel(s) ❌
Setting borderWidth to 1.8 will use 4.5 pixel(s) ❌
Setting borderWidth to 2 will use 5 pixel(s) ✔
Setting borderWidth to 0.4 will use 1 pixel(s) ✔

Testing with ratio of 3 (xxhdpi Android devices, iPhone 7 Plus, 8 Plus, X, XS, XS Max, 11 Pro, 11 Pro Max)

Setting borderWidth to 1 will use 3 pixel(s) ✔
Setting borderWidth to 1.3 will use 3.9000000000000004 pixel(s) ❌
Setting borderWidth to 1.5 will use 4.5 pixel(s) ❌
Setting borderWidth to 1.8 will use 5.4 pixel(s) ❌
Setting borderWidth to 2 will use 6 pixel(s) ✔
Setting borderWidth to 0.3333333333333333 will use 1 pixel(s) ✔

Testing with ratio of 3.5 (xxxhdpi Android devices)

Setting borderWidth to 1 will use 3 pixel(s) ✔
Setting borderWidth to 1.3 will use 3.9000000000000004 pixel(s) ❌
Setting borderWidth to 1.5 will use 4.5 pixel(s) ❌
Setting borderWidth to 1.8 will use 5.4 pixel(s) ❌
Setting borderWidth to 2 will use 6 pixel(s) ✔
Setting borderWidth to 0.3333333333333333 will use 1 pixel(s) ✔

Yup seems not really a lot of logic we can wrap around all this - sometimes it's working sometimes not. And for sure we can try to find exact calculation which will work for everything LOL. But based on the result - i do not see any possible fix which can be based on some logic. BTW what do you think about my comment above?

@narefyev91 Would you please share the results of setting a border width of 1.8 on iOS.
The idea of using a separator actually raises more questions. The View width is set to 1 so we will still get some blurry pixels but the issue would be reproducible. Why the issue only occur with borderWidth?

@narefyev91 Would you please share the results of setting a border width of 1.8 on iOS.
The idea of using a separator actually raises more questions. The View width is set to 1 so we will still get some blurry pixels but the issue would be reproducible. Why the issue only occur with borderWidth?

Interesting that width does not have the same effect of blurry pixels

@narefyev91 All values resulted in same width? That's weird

yup - i think IOS rounding that border to same value

@narefyev91 Do you have an update for your proposal? Mainly about the root cause, do you think the bug is on RN or Android itself
Also @narefyev91 thanks a lot your collaboration here. Such tiny bugs are sometimes the hardest.
Yup - hope i'm trying to help here a little bit 😁.
In my view - the issue is coming from RN - that doing a lot of custom logic for borders and border radius.

@narefyev91 Do you have an update for your proposal? Mainly about the root cause, do you think the bug is on RN or Android itself
Also @narefyev91 thanks a lot your collaboration here. Such tiny bugs are sometimes the hardest.

Yup - hope i'm trying to help here a little bit 😁. In my view - the issue is coming from RN - that doing a lot of custom logic for borders and border radius. Also this is old issue - but seems still has correct explanation why we see that issue with blurry border https://stackoverflow.com/a/24712372

@s77rt but also interesting that in flatter they have the same issue with 1px border https://github.com/flutter/flutter/issues/13675#issuecomment-759398861

@narefyev91 What do you propose to move forward?

@narefyev91 What do you propose to move forward?

I will suggest to move away from custom calculation for border - because based on your discovering we already have inconsistency between platforms. As solution should be generic - i will suggest to add Separator View - with width 1, in case that width in Android renders correctly - and do not have any issues with styling.

@s77rt This is an image from bare Android App
Issue still there - that's how Android renders it's own border

@narefyev91 Having blurry pixels is not an issue. As long as adjacent elements don't get drawn on those blurry pixels I'm okay with that.

@narefyev91 Having blurry pixels is not an issue. As long as adjacent elements don't get drawn on those blurry pixels I'm okay with that.

But blurry pixels are not counting as a wall to prevent View of start drawing inside that area

But on a bare Android App will they act as a wall?

But on a bare Android App will they act as a wall?

nope - it's doing the same as we already see

@narefyev91 Thank you! I have just asked on Slack on how we should move forward https://expensify.slack.com/archives/C01GTK53T8Q/p1682425579144149
cc @puneetlath

RETESTS SUMMARY
This fix is verified on Branch PR Draft narefyev91:add-new-separator-for-action-composer
Tests are conducted on the following devices:
Google Chrome Version 112.0.5615.121 (Official Build) (arm64) at Mac OS Ventura 13.3.1
Safari Version 16.4 (18615.1.26.11.23) at Mac OS Ventura 13.3.1
Expensify Desktop app - New Expensify Electron Version v1.3.1-0, Electron Version 22.3.6 (22.3.6)
iOS native app - iPhone Simulator Version 14.2 (986.5), iOS 16.2, SimulatorKit 627, CoreSimulator 885.2
Safari on iOS - iPhone Simulator 14 iOS 16.2
Android native app v1.3.1-0 - Android Emulator -Nexus_5X_API_TiramisuPrivacySandbox:5554
Chrome 101.0.4951.74, Operating system Android13; Build/TRA4.221021.001.B1
The above tests are executed with a 100% pass value

📣 @m4rtag! 📣
Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork.
Please follow these steps:

Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.

Format:
Contributor details
Your Expensify account email: <REPLACE EMAIL HERE>
Upwork Profile Link: <REPLACE LINK HERE>

@puneetlath, @s77rt, @narefyev91 Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

This is on staging.

The PR that introduced the bug has been identified: This is mostly a bug on Android. No PR to pinpoint here.
The offending PR has been commented on: n/a
A discussion in #expensify-bugs has been started: I don't think this is applicable here (cc @puneetlath).
Determine if we should create a regression test for this bug: No, this is a very low priority bug.

Thanks @s77rt. Checklist completed and contract offers sent.

All paid. Thanks everyone!

repo: Expensify/App


text:
wrong emoji suggestion priority order

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!

Action Performed:

type :rock

Expected results:
suggestions should be ranked on name matching first and then keywords but we don't see :rocket: (rocket) emoji until we reach :rocke . The suggestions till :rock have rock as substring in their keywords and not in name (except the rock emoji). This is not how its implemented in other apps like slack
Actual results:
keywords prioritized over title in emoji suggestion
Workaround:
Can the user still use Expensify without this being fixed? Have you informed them of the workaround?
Platforms:

Which of our officially supported platforms is this issue occurring on?

[x] Android / native
[x] Android / Chrome
[x] iOS / native
[x] iOS / Safari
[x] MacOS / Chrome / Safari
[x] MacOS / Desktop

Version Number: 1.3.8.8
Reproducible in staging?: y
Reproducible in production?: y
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos: Any additional supporting documentation

https://user-images.githubusercontent.com/43996225/235790004-02832dce-9df9-4fec-9074-192ef4bb26a4.mp4
In slack

Expensify/Expensify Issue URL:
Issue reported by: @chiragxarora
Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1683018206388899
View all open jobs on GitHub

Triggered auto assignment to @garrettmknight (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details.

Bug0 Triage Checklist (Main S/O)

[ ] This "bug" occurs on a supported platform (ensure Platforms in OP are ✅)
[ ] This bug is not a duplicate report (check E/App issues and #expensify-bugs)

If it is, comment with a link to the original report, close the issue and add any novel details to the original issue instead

[ ] This bug is reproducible using the reproduction steps in the OP. S/O

If the reproduction steps are clear and you're unable to reproduce the bug, check with the reporter and QA first, then close the issue.
If the reproduction steps aren't clear and you determine the correct steps, please update the OP.

[ ] This issue is filled out as thoroughly and clearly as possible

Pay special attention to the title, results, platforms where the bug occurs, and if the bug happens on staging/production.

[ ] I have reviewed and subscribed to the linked Slack conversation to ensure Slack/Github stay in sync

Proposal
Please re-state the problem that we are trying to solve in this issue.
Emoji suggestions list does not suggest the emoji user searches for
What is the root cause of that problem?
Root cause of the issue is wrong logic in suggestEmojis method in EmojiUtils.js.
https://github.com/Expensify/App/blob/74e5d322f1afb0f89c83860074e9079495b391e5/src/libs/EmojiUtils.js#L240-L265
What we are doing here is picking the matches from regex one by one and on each of them we perform following steps:

push the matched emoji in matching array
push all the suggestions of that emoji in matching array

This is wrong because when we add first matched emoji in the array, then for the same emoji we add all the suggestions and it exhausts the limit of suggestions which is 5. This way user does not get to see the emoji he searched for.
Example :rock does not show rocket emoji because first one is rock and remaining are the suggestion emojis of rock.
What changes do you think we should make in order to solve the problem?
We should modify the logic in a way that in the suggestions list, user first gets all the emojis with matching title that he searched for, and then if the limit is not yet reached, user sees the suggestion emojis of each. This can be done by breaking the main loop in two parts like this ...
function suggestEmojis(text, limit = 5) {
    const emojiData = text.match(CONST.REGEX.EMOJI_SUGGESTIONS);
    if (emojiData) {
        const matching = [];
        const nodes = emojisTrie.getAllMatchingWords(emojiData[0].toLowerCase().slice(1), limit);
        // first put all the matching titles
        for (let j = 0; j < nodes.length; j++) {
            if (nodes[j].metaData.code && !_.find(matching, obj => obj.name === nodes[j].name)) {
                if (matching.length === limit) {
                    return matching;
                }
                matching.push({code: nodes[j].metaData.code, name: nodes[j].name, types: nodes[j].metaData.types});
            }
        }
        // now put the suggestions of each
        for(let j=0;j<nodes.length;j++) {
            const suggestions = nodes[j].metaData.suggestions;
            for (let i = 0; i < suggestions.length; i++) {
                if (matching.length === limit) {
                    return matching;
                }
                if (!_.find(matching, obj => obj.name === suggestions[i].name)) {
                    matching.push(suggestions[i]);
                }
            }
        }
        return matching;
    }
    return [];
}

This is optimal because it gets the job done in same  O(n*m) time complexity as the original function
where n = maximum matched titles (nodes.length),
m = maximum suggestions length of a node

Results

What alternative solutions did you explore? (Optional)
None

Reproduced, opening up.

Job added to Upwork: https://www.upwork.com/jobs/~0197173baf284d3463

Current assignee @garrettmknight is eligible for the External assigner, not assigning anyone new.

Triggered auto assignment to Contributor-plus team member for initial proposal review - @thesahindia (External)

Triggered auto assignment to @cristipaval (External), see https://stackoverflow.com/c/expensify/questions/7972 for more details.

My proposal to another related issue can solve this: https://github.com/Expensify/App/issues/15946#issuecomment-1471204650 though it was closed long ago. FIY, I don't know if there's any coincidence but the above proposal looks somewhat similar to my proposal.

Just saw the issue you shared, it does look similar but the solution we've shared is pretty generic and it's the first improvement that comes to mind on seeing suggestEmojis  implementation.
Though that issue is closed for 2 months+ now, I don't see any relevance of that here

@thesahindia any of these look like they'll do the job?

Good catch - I'll close.

source: gharchive/issue

authors: MelvinBot chiragxarora garrettmknight kavimuru tienifr

license: MIT

license_type: permissive

license_source: github-api


text:
Chat - Chat with new user is opened with double welcome message and two image icon

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!

Action Performed:
Precondition: login with HT account

Click the green + icon and select request money
Enter an amount and click next
Enter the email address of a user that doesn't have an existing account and request $x to confirm and send the request

Expected Result:
Chat with new user is opened with one welcome message and one image icon.
Actual Result:
Chat with new user is opened with double welcome message and two image icon.
Workaround:
Unknown
Platforms:

Which of our officially supported platforms is this issue occurring on?

[x] Android / native
[x] Android / Chrome
[x] iOS / native
[x] iOS / Safari
[x] MacOS / Chrome / Safari
[x] MacOS / Desktop

Version Number: 1.3.14.4
Reproducible in staging?: yes
Reproducible in production?: yes
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos: Any additional supporting documentation

https://github.com/Expensify/App/assets/93399543/854505c6-4a4e-45ff-b742-b909dcf07db3
Expensify/Expensify Issue URL:
Issue reported by: Applause - Internal Team
Slack conversation:
View all open jobs on GitHub

Proposal
Please re-state the problem that we are trying to solve in this issue.
The Pressable is taking the space of the entire action item instead of just the IOUPreview component.
What is the root cause of that problem?
This is default behaviour of react native, components (In this case Pressable) expand to fill it's parent as react native follows a flexbox system to style components.
What changes do you think we should make in order to solve the problem?

To resolve this, we simply apply the IOUPreview component styles to the Pressable instead of the View.
What alternative solutions did you explore? (Optional)
None.

Precondition: login with HT account

@kbecciv - what is an HT account?

HT is High Traffic Account (policy with over 10k users with high amount of conversation data)

im not able to reproduce this:

can't repro, so im closing.

authors: kbecciv maddylewis therealsujitk


text:
DEV: 'You'll lose any offline changes if you sign-out.' message appears even if you are online

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!

Action Performed:

go to Settings
click on Sign out button

Expected Result:
user should be Sign out
Actual Result:
shows 'You'll lose any offline changes if you sign-out.' message even if you are online
Workaround:
Can the user still use Expensify without this being fixed? Have you informed them of the workaround?
Platforms:

Which of our officially supported platforms is this issue occurring on?

[ ] Android / native
[ ] Android / Chrome
[ ] iOS / native
[ ] iOS / Safari
[x] MacOS / Chrome / Safari
[ ] MacOS / Desktop

Version Number: Dev
Reproducible in staging?: dev
Reproducible in production?: dev
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Notes/Photos/Videos: Any additional supporting documentation
https://github.com/Expensify/App/assets/43996225/cfd52b31-a124-408d-a1d8-d1f95837c19d
Expensify/Expensify Issue URL:
Issue reported by: @gadhiyamanan
Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1690436737183979
View all open jobs on GitHub

I can't reproduce it.

This is regression from https://github.com/Expensify/App/issues/16281#issuecomment-1652952760

:wave: Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open StagingDeployCash deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

Identify the pull request that introduced this issue and revert it.
Find someone who can quickly fix the issue.
Fix the issue yourself.

@mountiny @slafortune  this is a regression from https://github.com/Expensify/App/issues/16281. Awaiting response on this.

@mananjadhav given its deploy blocker and the contributor hasnt messaged I have created the PR

@mountiny I’ll be able go check this in an hour, afk

No problem merged going to CP

@slafortune Can we pay @gadhiyamanan $250 for reporting this bug?

@gadhiyamanan offer sent here - https://www.upwork.com/nx/wm/offer/25815360

@slafortune offer accepted, thanks!

Thanks - Paid!

authors: OSBotify alphaboss1104 gadhiyamanan kavimuru mananjadhav mountiny slafortune


text:
[HOLD for payment 2024-02-07] [$500] Web - Public room - Not here page or different report opens each time Sign-in modal opens

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!

Version Number: .4.27-1
Reproducible in staging?: Y
Reproducible in production?: Y
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: Applause - Internal Team
Slack conversation:
Action Performed:

Log out if logged in
Navigate to public room (https://staging.new.expensify.com/r/2376199970894587
)
Click Sign in button from LHN
Close the modal
Click Sign in button from LHN
Note that not here page opens in background
Repeat Step 4 and 5

Expected Result:
When sign-in modal opens, the chat opened in the background will not be affected
Actual Result:
When sign-in modal opens, Not here page opens (Step 5). Each time sign-in modal opens, it opens different chat (Step 7)
Workaround:
Unknown
Platforms:

Which of our officially supported platforms is this issue occurring on?

[ ] Android: Native
[ ] Android: mWeb Chrome
[ ] iOS: Native
[ ] iOS: mWeb Safari
[x] MacOS: Chrome / Safari
[ ] MacOS: Desktop

Screenshots/Videos
Add any screenshot/video evidence

https://github.com/Expensify/App/assets/78819774/8a3b4300-d068-49cf-bd60-3dacd2924c7e
View all open jobs on GitHub
Upwork Automation - Do Not Edit

Upwork Job URL: https://www.upwork.com/jobs/~017ab441e20c642fc9
Upwork Job ID: 1748070237674250240
Last Price Increase: 2024-01-18
Automatic offers:

s-alves10 | Contributor | 28117506

#vip-vsb

Proposal
Please re-state the problem that we are trying to solve in this issue.
Different report opens each time sign-in modal opens in public room
What is the root cause of that problem?
https://github.com/Expensify/App/blob/31b19eaaf00c23492c6e5132b9501abdeb210e78/src/pages/home/sidebar/SignInButton.js#L19
https://github.com/Expensify/App/blob/31b19eaaf00c23492c6e5132b9501abdeb210e78/src/pages/home/sidebar/SignInButton.js#L26
As you can see above, we call Session.signOutAndRedirectToSignIn function when sign-in button is pressed
Now let's take a look at signOutAndRedirectToSignIn function
https://github.com/Expensify/App/blob/31b19eaaf00c23492c6e5132b9501abdeb210e78/src/libs/actions/Session/index.ts#L104
This function takes one parameter shouldReplaceCurrentScreen and as you can see below, if shouldReplaceCurrentScreen is truthy, it replaces the current route with sign-in modal
https://github.com/Expensify/App/blob/31b19eaaf00c23492c6e5132b9501abdeb210e78/src/libs/actions/Session/index.ts#L114-L118
shouldReplaceCurrentScreen has default value false. But onPress handler has event parameter. We are intended to call signOutAndRedirectToSignIn function with no parameter but event value is passed to the function. That's why shouldReplaceCurrentScreen has truthy value and so the below code is executed.
https://github.com/Expensify/App/blob/31b19eaaf00c23492c6e5132b9501abdeb210e78/src/libs/actions/Session/index.ts#L115
This is the root cause
What changes do you think we should make in order to solve the problem?
We need to call the signOutAndRedirectToSignIn with no parameter
https://github.com/Expensify/App/blob/31b19eaaf00c23492c6e5132b9501abdeb210e78/src/pages/home/sidebar/SignInButton.js#L19
https://github.com/Expensify/App/blob/31b19eaaf00c23492c6e5132b9501abdeb210e78/src/pages/home/sidebar/SignInButton.js#L26
In the above code, replace Session.signOutAndRedirectToSignIn with () => Session.signOutAndRedirectToSignIn()
This works as expected

Result

What alternative solutions did you explore? (Optional)

@allroundexperts does this proposal look viable?

@s-alves10's proposal looks good to me!
🎀 👀 🎀 C+ reviewed

Summary of payment:

Contributor: @s-alves10 $500 paid via Upwork
Reviewer: @allroundexperts $500

Reviewer Checklist

https://github.com/Expensify/App/pull/24414
https://github.com/Expensify/App/pull/24414/files#r1493097611
N/A
A regression test would be helpful here. The test steps mentioned in the OP look clear enough to me.

QA updated - @aimane-chnaif on you to request payment.

Yep - sorry about that.

$500 approved for @allroundexperts based on this summary.


text:
Search - Unable to download reports to CSV on native apps

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!

Version Number: 9.0.9-1
Reproducible in staging?: Y
Reproducible in production?: Y
If this was caught during regression testing, add the test name, ID and link from TestRail: N/A
Issue reported by: Applause - Internal Team
Issue found when executing PR https://github.com/Expensify/App/pull/45642
Action Performed:

Open the app
Log in with an account that has reporth on the Search - Shared tab
Navigate to Search - Shared
Long tap on a report
Tap on the "Select" button
Tap on the "Select all" checkbox
Tap on "X selected"

Expected Result:
I should be able to download
Actual Result:
Unable to download reports to CSV on native apps. It displays "No options available for the selected group of expenses."
Workaround:
Unknown
Platforms:

Which of our officially supported platforms is this issue occurring on?

[x] Android: Native
[ ] Android: mWeb Chrome
[x] iOS: Native
[ ] iOS: mWeb Safari
[ ] MacOS: Chrome / Safari
[ ] MacOS: Desktop

Screenshots/Videos
Add any screenshot/video evidence

https://github.com/user-attachments/assets/ed584132-93fa-4846-ba89-73e7eed72219
View all open jobs on GitHub

@trjExpensify  FYI I haven't added the External label as I wasn't 100% sure about this issue. Please take a look and add the label if you agree it's a bug and can be handled by external contributors

Forgot to add to testing notes, but download is not supported in native apps yet, we can close this one.


text:
[$250]  Hybrid App - The Duplicate flag on an expense cannot be dismissed, even if there are no duplicates

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!

Version Number: 9.0.46-2
Reproducible in staging?: y
Reproducible in production?: y
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: @jasonli
Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1728377645999889
Action Performed:

SmartScan receipt with the same name as a previous duplicate
See the red dot in expense
Click into expense and edit merchant

Expected Result:
Duplicate flag disappear
Actual Result:
See that the duplicate flag remains
Workaround:
unknown
Platforms:

Which of our officially supported platforms is this issue occurring on?

[x] Android: Native
[ ] Android: mWeb Chrome
[ ] iOS: Native
[ ] iOS: mWeb Safari
[ ] MacOS: Chrome / Safari
[ ] MacOS: Desktop

Screenshots/Videos
https://github.com/user-attachments/assets/f3f5bdfc-6ec6-4108-b036-d4eb2fbfcff8
https://github.com/user-attachments/assets/2dad2015-0817-4fd8-87cb-93bd32b2782f

Add any screenshot/video evidence

View all open jobs on GitHub
Upwork Automation - Do Not Edit

Upwork Job URL: https://www.upwork.com/jobs/~021844741371771684057
Upwork Job ID: 1844741371771684057
Last Price Increase: 2024-10-11

Issue OwnerCurrent Issue Owner: @hoangzinh

@RachCHopkins I'm going ooo until Oct 20. Adding another BZ member until I return, then I can take it back.
STATUS: waiting on proposals for fix

Pending proposals.

This is a backend issue. transactionViolations_ does not update its values after themerchant is updated and remains unchanged even when I set it to [] or null in optimisticData.

I'm back from ooo - unassigning @RachCHopkins

@hoangzinh

@abekkala could you add an internal label to grab an internal engineer to this issue?

this does not auto-assign an engineer - at this stage if there is not an auto-assigner available. If you're unsure of the BE fix and looking for an internal input you may want to discuss in Slack first. If it's determined that it's an internal BE fix then we can apply the hot pick for an internal engineer to volunteer to pick up.

@jliexpensify THis is not a bug, it has worked like that since duplicate detection was created years and years ago :smile: Merchant does not signal if an expense is a duplicate. Two expenses are duplicates if they have the same amount, currency and date

authors: RachCHopkins abekkala huult m-natarajan pecanoro


text:
Add label check

Details

As per discussion with @AndrewGable a label check was added in order to have an opportunity to mark a PR as Ready To Build to allow building apps from it.
Fixed Issues

$ GH_LINK
PROPOSAL: GH_LINK_ISSUE(COMMENT)
Tests

[x] Verify that no errors appear in the JS console

Offline tests

QA Steps

[x] Verify that no errors appear in the JS console

PR Author Checklist

[x] I linked the correct issue in the ### Fixed Issues section above
[x] I wrote clear testing steps that cover the changes made in this PR

[x] I added steps for local testing in the Tests section
[x] I added steps for the expected offline behavior in the Offline steps section
[x] I added steps for Staging and/or Production testing in the QA steps section
[x] I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
[x] I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
[x] I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).

[x] I included screenshots or videos for tests on all platforms
[x] I ran the tests on all platforms & verified they passed on:

[x] Android / native
[x] Android / Chrome
[x] iOS / native
[x] iOS / Safari
[x] MacOS / Chrome / Safari
[x] MacOS / Desktop

[x] I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
[x] I followed proper code patterns (see Reviewing the code)

[x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
[x] I verified that comments were added to code that is not self explanatory
[x] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
[x] I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
[x] I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
[x] I verified any copy / text that was added to the app is correct English and approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
[x] I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
[x] I verified the JSDocs style guidelines (in STYLE.md) were followed

[x] If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
[x] I followed the guidelines as stated in the Review Guidelines
[x] I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
[x] I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
[x] I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
[x] I verified that if a function's arguments changed that all usages have also been updated correctly
[x] If a new component is created I verified that:

[x] A similar component doesn't exist in the codebase
[x] All props are defined accurately and each prop has a /** comment above it */
[x] The file is named correctly
[x] The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
[x] The only data being stored in the state is data necessary for rendering and nothing else
[x] For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
[x] Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
[x] All JSX used for rendering exists in the render method
[x] The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions

[x] If any new file was added I verified that:

[x] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory

[x] If a new CSS style is added I verified that:

[x] A similar style doesn't already exist
[x] The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)

[x] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
[x] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
[x] If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
[x] I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

Screenshots/Videos

Web

Mobile Web - Chrome

Mobile Web - Safari

Desktop

iOS

Android

Reviewer Checklist

[ ] I have verified the author checklist is complete (all boxes are checked off).
[ ] I verified the correct issue is linked in the ### Fixed Issues section above
[ ] I verified testing steps are clear and they cover the changes made in this PR

[ ] I verified the steps for local testing are in the Tests section
[ ] I verified the steps for Staging and/or Production testing are in the QA steps section
[ ] I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
[ ] I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)

[ ] I checked that screenshots or videos are included for tests on all platforms
[ ] I included screenshots or videos for tests on all platforms
[ ] I verified tests pass on all platforms & I tested again on:

[ ] Android / native
[ ] Android / Chrome
[ ] iOS / native
[ ] iOS / Safari
[ ] MacOS / Chrome / Safari
[ ] MacOS / Desktop

[ ] If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
[ ] I verified proper code patterns were followed (see Reviewing the code)

[ ] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick).
[ ] I verified that comments were added to code that is not self explanatory
[ ] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
[ ] I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
[ ] I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
[ ] I verified any copy / text that was added to the app is correct English and approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
[ ] I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
[ ] I verified the JSDocs style guidelines (in STYLE.md) were followed

[ ] If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
[ ] I verified that this PR follows the guidelines as stated in the Review Guidelines
[ ] I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
[ ] I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
[ ] I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
[ ] If a new component is created I verified that:

[ ] A similar component doesn't exist in the codebase
[ ] All props are defined accurately and each prop has a /** comment above it */
[ ] The file is named correctly
[ ] The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
[ ] The only data being stored in the state is data necessary for rendering and nothing else
[ ] For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
[ ] Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
[ ] All JSX used for rendering exists in the render method
[ ] The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions

[ ] If any new file was added I verified that:

[ ] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory

[ ] If a new CSS style is added I verified that:

[ ] A similar style doesn't already exist
[ ] The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)

[ ] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
[ ] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
[ ] If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
[ ] I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

Web

Mobile Web - Chrome

Mobile Web - Safari

Desktop

iOS

Android

:hand: 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 staging by @AndrewGable in version: 1.2.46-0 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

🚀 Deployed to production by @roryabraham in version: 1.2.46-0 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

source: gharchive/pull-request

authors: AndrewGable OSBotify staszekscp


text:
Better offline route fetching

Details

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/310081
PROPOSAL:
Tests

Go offline, go to the distance request page
Enter in valid addresses in both fields
Go back online
Go back to the distance request page
Verify that a route was generated successfully
Change one of the waypoints to a different destination
Verify the route was updated successfully

Offline tests
Same as above
QA Steps
Same as tests
PR Author Checklist

[x] I linked the correct issue in the ### Fixed Issues section above
[x] I wrote clear testing steps that cover the changes made in this PR

[x] I added steps for local testing in the Tests section
[x] I added steps for the expected offline behavior in the Offline steps section
[x] I added steps for Staging and/or Production testing in the QA steps section
[x] I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
[x] I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
[x] I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).

[x] I included screenshots or videos for tests on all platforms
[x] I ran the tests on all platforms & verified they passed on:

[x] Android / native
[x] Android / Chrome
[x] iOS / native
[x] iOS / Safari
[x] MacOS / Chrome / Safari
[x] MacOS / Desktop

[x] I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
[x] I followed proper code patterns (see Reviewing the code)

[x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
[x] I verified that the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. myBool && <MyComponent />.
[x] I verified that comments were added to code that is not self explanatory
[x] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
[x] I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method

[x] If any non-english text was added/modified, I verified the translation was requested/reviewed in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:

[x] I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
[x] I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
[x] I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
[x] I verified the JSDocs style guidelines (in STYLE.md) were followed

[x] If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
[x] I followed the guidelines as stated in the Review Guidelines
[x] I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
[x] I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
[x] I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
[x] I verified that if a function's arguments changed that all usages have also been updated correctly
[x] If a new component is created I verified that:

[x] A similar component doesn't exist in the codebase
[x] All props are defined accurately and each prop has a /** comment above it */
[x] The file is named correctly
[x] The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
[x] The only data being stored in the state is data necessary for rendering and nothing else
[x] If we are not using the full Onyx data that we loaded, I've added the proper selector in order to ensure the component only re-renders when the data it is using changes
[x] For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
[x] Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
[x] All JSX used for rendering exists in the render method
[x] The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions

[x] If any new file was added I verified that:

[x] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory

[x] If a new CSS style is added I verified that:

[x] A similar style doesn't already exist
[x] The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG))

[x] If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
[x] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
[x] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
[x] If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
[x] If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
[x] If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
[x] I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

Screenshots/Videos

Web

https://github.com/Expensify/App/assets/30609178/99b6aa91-5337-4cd6-ac14-068a246f8ac9

Mobile Web - Chrome

https://github.com/Expensify/App/assets/30609178/539afffb-7563-4f63-bc84-9299878d0288

Mobile Web - Safari

https://github.com/Expensify/App/assets/30609178/f4b5ffb6-cbbf-4053-980e-981d02ffb373

Desktop

https://github.com/Expensify/App/assets/30609178/78333958-c607-4705-8f63-0b40f93a4498

iOS

https://github.com/Expensify/App/assets/30609178/ef9de921-6d8c-40f9-8fbb-033b8885e57f

Android

Uploading Screen Recording 2023-08-30 at 5.02.53 PM.mov…

I'm noticing that getting the route on iOS/mWeb is very slow but it does work

Nice nice, love to see it

I'm deploying today so should be ready later today - though the changes should be on staging already if you want to test with the staging server

Removing the hold as @allroundexperts can start testing using the staging server

That's unrelated to the get route changes though, I think that has to do with the access token

:hand: 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 staging by https://github.com/thienlnam in version: 1.3.62-0 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

🚀 Deployed to production by https://github.com/mountiny in version: 1.3.62-4 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

authors: OSBotify thienlnam


text:
[No QA] Fix deployBlocker workflow

Details
Fixing failed workflow
Fixed Issues
$ n/a
Tests

Merge this PR
Mark another issue with special characters like ' or " or | in the title as a deploy blocker
Verify it's added to the checklist
Verify it's announced in slack

[x] Verify that no errors appear in the JS console

Offline tests
None.
QA Steps
None.

[x] Verify that no errors appear in the JS console

PR Author Checklist

[x] I linked the correct issue in the ### Fixed Issues section above
[x] I wrote clear testing steps that cover the changes made in this PR

[x] I added steps for local testing in the Tests section
[x] I added steps for the expected offline behavior in the Offline steps section
[x] I added steps for Staging and/or Production testing in the QA steps section
[x] I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
[x] I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
[x] I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).

[x] I included screenshots or videos for tests on all platforms
[x] I ran the tests on all platforms & verified they passed on:

[x] Android: Native
[x] Android: mWeb Chrome
[x] iOS: Native
[x] iOS: mWeb Safari
[x] MacOS: Chrome / Safari
[x] MacOS: Desktop

[x] I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
[x] I followed proper code patterns (see Reviewing the code)

[x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
[x] I verified that the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. myBool && <MyComponent />.
[x] I verified that comments were added to code that is not self explanatory
[x] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
[x] I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method

[x] If any non-english text was added/modified, I verified the translation was requested/reviewed in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:

[x] I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
[x] I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
[x] I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
[x] I verified the JSDocs style guidelines (in STYLE.md) were followed

[x] If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
[x] I followed the guidelines as stated in the Review Guidelines
[x] I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
[x] I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
[x] I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
[x] I verified that if a function's arguments changed that all usages have also been updated correctly
[x] If any new file was added I verified that:

[x] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory

[x] If a new CSS style is added I verified that:

[x] A similar style doesn't already exist
[x] The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG))

[x] If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
[x] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
[x] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
[x] If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
[x] If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
[x] If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native

Android: mWeb Chrome

iOS: Native

iOS: mWeb Safari

MacOS: Chrome / Safari

MacOS: Desktop

The replace logic is weird and depends upon a nuance of the slack action – you can basically pass it JS and it will run it? You can see we used to have something similar here, so this is basically a simplifed version that does only one replace and doesn't rely on this very confusing sed

:hand: 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 staging by https://github.com/luacmartins in version: 1.4.2-0 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

🚀 Deployed to production by https://github.com/luacmartins in version: 1.4.2-3 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

authors: OSBotify roryabraham


text:
fix: Category - No hover effect when hovering over selected parent category in the list.

Details

Fixed Issues
$ https://github.com/Expensify/App/issues/42936
PROPOSAL: https://github.com/Expensify/App/issues/42936#issuecomment-2142609940
Tests
Precondition:

Workspace has parent and child categories.
e.g., (Color, Color: Red, Color: Yellow)

Go to workspace chat
Go to + > Submit expenses > Manual
Proceed to confirmation page
Click Category
Select the Parent category
Click Category
Hover over Parent category in the list (not the parent category that is on the top, it is the category in the list with the child categories)
Verify the text of the parent category in the list is not greyed out and category has the hover effect

[x] Verify that no errors appear in the JS console

Offline tests
Precondition:

Workspace has parent and child categories.
e.g., (Color, Color: Red, Color: Yellow)

Go to workspace chat
Go to + > Submit expenses > Manual
Proceed to confirmation page
Click Category
Select the Parent category
Click Category
Hover over Parent category in the list (not the parent category that is on the top, it is the category in the list with the child categories)
Verify the text of the parent category in the list is not greyed out and category has the hover effect

QA Steps
Precondition:

Workspace has parent and child categories.
e.g., (Color, Color: Red, Color: Yellow)

Go to workspace chat
Go to + > Submit expenses > Manual
Proceed to confirmation page
Click Category
Select the Parent category
Click Category
Hover over Parent category in the list (not the parent category that is on the top, it is the category in the list with the child categories)
Verify the text of the parent category in the list is not greyed out and category has the hover effect

[x] Verify that no errors appear in the JS console

PR Author Checklist

[x] I linked the correct issue in the ### Fixed Issues section above
[x] I wrote clear testing steps that cover the changes made in this PR

[x] I added steps for local testing in the Tests section
[x] I added steps for the expected offline behavior in the Offline steps section
[x] I added steps for Staging and/or Production testing in the QA steps section
[x] I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
[x] I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
[x] I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).

[x] I included screenshots or videos for tests on all platforms
[x] I ran the tests on all platforms & verified they passed on:

[x] Android: Native
[x] Android: mWeb Chrome
[x] iOS: Native
[x] iOS: mWeb Safari
[x] MacOS: Chrome / Safari
[x] MacOS: Desktop

[x] I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
[x] I followed proper code patterns (see Reviewing the code)

[x] I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
[x] I verified that the left part of a conditional rendering a React component is a boolean and NOT a string, e.g. myBool && <MyComponent />.
[x] I verified that comments were added to code that is not self explanatory
[x] I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
[x] I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method

[x] If any non-english text was added/modified, I verified the translation was requested/reviewed in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:

[x] I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
[x] I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
[x] I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
[x] I verified the JSDocs style guidelines (in STYLE.md) were followed

[x] If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
[x] I followed the guidelines as stated in the Review Guidelines
[x] I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
[x] I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
[x] I verified any variables that can be defined as constants (ie. in CONST.js or at the top of the file that uses the constant) are defined as such
[x] I verified that if a function's arguments changed that all usages have also been updated correctly
[x] If any new file was added I verified that:

[x] The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory

[x] If a new CSS style is added I verified that:

[x] A similar style doesn't already exist
[x] The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))

[x] If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
[x] If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
[x] If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
[x] If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
[x] If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:

[x] I verified that all the inputs inside a form are aligned with each other.
[x] I added Design label and/or tagged @Expensify/design so the design team can review the changes.

[x] If a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
[x] If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native
https://github.com/Expensify/App/assets/85894871/f15e44e1-f295-4ddd-baa1-3e153c83fbe2

Android: mWeb Chrome
https://github.com/Expensify/App/assets/85894871/c42dfe75-69fe-4cd1-96d0-5f56b63d23e6

iOS: Native
https://github.com/Expensify/App/assets/85894871/28996d14-60af-4116-957f-bd11c52db85c

iOS: mWeb Safari
https://github.com/Expensify/App/assets/85894871/4fbb154c-1387-4efe-aa64-ec8535957670

MacOS: Chrome / Safari
https://github.com/Expensify/App/assets/85894871/305737e1-464b-4fc9-a646-3aa87e5bf37e

MacOS: Desktop
https://github.com/Expensify/App/assets/85894871/5dc1d629-b1ce-4add-8b08-ec82acc63f79

:hand: 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 staging by https://github.com/nkuoch in version: 9.0.4-0 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

🚀 Cherry-picked to staging by https://github.com/tgolen in version: 9.0.4-5 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

@Expensify/applauseleads please QA this PR and check it off on the deploy checklist if it passes.

🚀 Deployed to production by https://github.com/Julesssss in version: 9.0.5-13 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅

🚀 Deployed to production by https://github.com/thienlnam in version: 9.0.6-8 🚀

platform
result

🤖 android 🤖
success ✅

🖥 desktop 🖥
success ✅

🍎 iOS 🍎
success ✅

🕸 web 🕸
success ✅