Skip to content

Conversation

@rinej
Copy link
Contributor

@rinej rinej commented Jul 15, 2025

Explanation of Change

Fixed Issues

$ #63253
PROPOSAL: #63253 (comment)

Tests

  • Open Reports > Expense Reports
  • Open an expense report with multiple transactions on it
  • Open one transaction thread
  • Ensure the transaction details are loaded immediately (since all the transaction data should be available)
  • Use the arrows in the header to cycle through the expense views
  • The transaction details should be visible immediately even if the report actions are loading

Tests flow after regression detection:
Original issue: #66109

  • Go to staging.expensify.com
  • Open FAB > Create expense > Manual.
  • Submit two expenses to any user.
  • Open expense report.
  • Open any expense row.
  • Click More.
  • Hold and Delete option are present in More menu.

Original issue: #66110

  • Open workspace chat.
  • Submit a manual expense.
  • Open the just created report.
  • Scroll to the top of the report.
  • Note that a big space with no content can be seen above receipt thumbnail.
  • User shouldn´t be able to scroll up above the receipt thumbnail on expense report.

Offline tests

QA Steps

  • Same as tests.

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover 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 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).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
    • MacOS: Desktop
  • 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)
  • I verified there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (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
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • 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 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)
    • 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 followed the guidelines as stated in the Review Guidelines
  • 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)
  • 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.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • 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(theme.componentBG))
  • 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.
  • 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 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.
  • 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:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • 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 added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • 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
Transaction-android.mp4
Android: mWeb Chrome
Transaction-androidWeb.mp4
iOS: Native
ios-Transaction.mp4
iOS: mWeb Safari
Transaction-iosWeb.mp4
MacOS: Chrome / Safari
Transaction-Web.mp4
MacOS: Desktop
Transaction-Desktop.mp4

Copy link
Contributor

@allgandalf allgandalf left a comment

Choose a reason for hiding this comment

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

nit pics

Comment on lines 66 to 67
/** If this report is a transaction thread report */
isReportTransactionThread?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/** If this report is a transaction thread report */
isReportTransactionThread?: boolean;
/** If the report is a transaction thread report */
isReportTransactionThread?: boolean;

policyAvatar: reportOnyx.policyAvatar,
},
[reportOnyx, reportNameValuePairsOnyx, permissions],
// This is required to get the transaction data from the parent report, to render the optimistic transaction thread
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 elaborate more on what this means , better for future context

Comment on lines 138 to 141
const reportIDFromRoute = getNonEmptyStringOnyxID(route.params?.reportID);
const reportActionIDFromRoute = route?.params?.reportActionID;
const parentReportIDFromRoute = route?.params?.parentReportID;
const parentReportActionIDFromRoute = route?.params?.parentReportActionID;
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 instead do:

const {reportActionIDFromRoute, parentReportIDFromRoute, parentReportActionIDFromRoute} = route?.params;

},
};
}),
[translate, parentReportAction, transaction, reportID, report],
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 please fix this warning

Comment on lines 150 to 160
const getStatusIcon: (src: IconAsset) => ReactNode = useCallback(
(src) => (
<Icon
src={src}
height={variables.iconSizeSmall}
width={variables.iconSizeSmall}
fill={theme.icon}
/>
),
[theme.icon],
);
Copy link
Contributor

Choose a reason for hiding this comment

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

does the following way to write this not work?:

const getStatusIcon = useCallback((src: IconAsset) => (
    <Icon
        src={src}
        height={variables.iconSizeSmall}
        width={variables.iconSizeSmall}
        fill={theme.icon}
    />
), [theme.icon]);

@rinej rinej marked this pull request as ready for review July 22, 2025 10:57
@rinej rinej requested a review from a team as a code owner July 22, 2025 10:57
@melvin-bot melvin-bot bot requested review from allgandalf and removed request for a team July 22, 2025 10:57
@melvin-bot
Copy link

melvin-bot bot commented Jul 22, 2025

@allgandalf Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button]

@pac-guerreiro
Copy link
Contributor

@allgandalf all feedback addressed and PR is ready for review! YOU SHALL PASS this PR 😎

@github-actions
Copy link
Contributor

🚧 @mountiny has triggered a test Expensify/App build. You can view the workflow run here.

@github-actions

This comment has been minimized.

Copy link
Contributor

@allgandalf allgandalf left a comment

Choose a reason for hiding this comment

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

codewise LGTM, testing now

@rinej
Copy link
Contributor Author

rinej commented Aug 5, 2025

@allgandalf Thanks for review and finding the issue. I added the fix for it. Please have a look now :)

fixed-bottom-scrolling.mov

src/ROUTES.ts Outdated
Comment on lines 119 to 125
if (parentReportID) {
queryParams.push(`parentReportID=${parentReportID}`);
}

if (parentReportActionID) {
queryParams.push(`parentReportActionID=${parentReportActionID}`);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

@WojtekBoman @adamgrzybowski @pac-guerreiro @rinej I think we will need to find a way to handle this differently. Check out the routing philosophy https://github.com/Expensify/App/blob/main/contributingGuides/philosophies/ROUTING.md#--should-not-use-query-parameters

We should not use the query params, and I don't think this is an exception that should apply, as it's quite a common URL.

@rinej can you please summarise why these params are needed in the route? Let's find a different solution for this than the query params.

Copy link
Contributor

@WojtekBoman WojtekBoman Aug 6, 2025

Choose a reason for hiding this comment

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

It won't be a beautiful solution, but according to this rule from the routing philosophy:

- SHOULD NOT use optional parameters
If there are optional parameters, use two separate route definitions instead to be explicit.

we should have 4 different routes based on the available params.
Please remember to correctly extend the screen type

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 an example of the screen component type that is shared between two routes https://github.com/Expensify/App/blob/main/src/pages/iou/HoldReasonPage.tsx

type HoldReasonPageProps =
    | PlatformStackScreenProps<MoneyRequestNavigatorParamList, typeof SCREENS.MONEY_REQUEST.HOLD>
    | PlatformStackScreenProps<SearchReportParamList, typeof SCREENS.SEARCH.TRANSACTION_HOLD_REASON_RHP>;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As I analyse it the the parentReportID and parentReportActionID were added to enable immediate display of transaction details even while report actions are still loading, so we have the necessary parent context to load related data upfront via useOnyx (in ReportScreen.tsx).
Without these parameters, we have have to wait through a loading sequence (transaction thread → parent report → parent action → transaction details), so we see the loading screen.

I think it was the fundamental idea of @pac-guerreiro to resolve the initial issue.

@WojtekBoman even if we create separate routes for each available parameter, it still wouldn’t be ideal according to the rules, since we’re supposed to avoid including ANY new parameters there - is that correct?"

Copy link
Contributor

Choose a reason for hiding this comment

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

Which rule are you referring to - avoid including ANY new parameters there? I'd like to make sure we're on the same page :) I see this rule can be broken:

- SHOULD use only the minimal necessary information to render the page
Examples:

r/:threadReportID GOOD - threadReportID is all that is needed and all the rest of the page can be derived from that
r/:parentReportID/:threadReportID BAD - the parentReportID is not necessary so it just adds cruft to the URL

On the other hand, if it makes loading faster, I think we can assume it's necessary cc: @mountiny

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, I will investigate and try to find another way for it

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe cache it in sessionStorage or something like that? We wouldn't need to take care of cleaning this information.

Copy link
Contributor

Choose a reason for hiding this comment

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

bump @rinej on comments ^

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 tried another solution that didn’t require passing those parameters, but it ended up breaking the other report screens.

I’m now testing an approach that uses sessionStorage. The idea is to move the parameters from the navigation route into session storage.

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks, lets make sure it works as expected on all platforms

@rinej
Copy link
Contributor Author

rinej commented Aug 11, 2025

@allgandalf @mountiny
I updated the code to store and retrieve the parameters from session storage instead of using navigation parameters.

I left the rest of the code untouched as possible to preserve existing features, such as automatically scrolling to the bottom by default.
Here’s how it looks on the web:

web-transaciton-v2.mov

@mountiny
Copy link
Contributor

@rinej love it, thank you! Are we clearing the sessions storage upon signing out?

@github-actions
Copy link
Contributor

🚧 @mountiny has triggered a test Expensify/App build. You can view the workflow run here.

@github-actions
Copy link
Contributor

🧪🧪 Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! 🧪🧪
Built from App PR #66165.

Android 🤖 iOS 🍎
❌ FAILED ❌ https://ad-hoc-expensify-cash.s3.amazonaws.com/ios/66165/index.html
The QR code can't be generated, because the Android build failed iOS
Desktop 💻 Web 🕸️
https://ad-hoc-expensify-cash.s3.amazonaws.com/desktop/66165/NewExpensify.dmg https://66165.pr-testing.expensify.com
Desktop Web

👀 View the workflow run that generated this build 👀

@allgandalf
Copy link
Contributor

allgandalf commented Aug 12, 2025

Bug: Transaction table goes away after we navigate to a expesne:

Screen.Recording.2025-08-12.at.10.31.42.AM.mov

@allgandalf
Copy link
Contributor

Follow up bug: The user is not navigated back to the workspace chat when clicking on header link afterwards:

Screen.Recording.2025-08-12.at.10.23.56.AM.mov

@allgandalf
Copy link
Contributor

Follow up Bug: Each workspace chat i click after opening the expense has an expense at the top of it

Screen.Recording.2025-08-12.at.10.24.54.AM.mov

@allgandalf
Copy link
Contributor

Bug: No unread message indicator

Screen.Recording.2025-08-12.at.10.26.30.AM.mov

Copy link
Contributor

@allgandalf allgandalf left a comment

Choose a reason for hiding this comment

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

please check the ^

@rinej rinej mentioned this pull request Aug 14, 2025
51 tasks
…-skeleton

# Conflicts:
#	src/pages/home/report/ReportActionsList.tsx
…-skeleton

# Conflicts:
#	src/components/MoneyRequestReportView/MoneyRequestReportView.tsx
@pac-guerreiro
Copy link
Contributor

@rinej we can close this one 😄

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.

7 participants