Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[$250] Reports - "Nothing to show" shown on chats, when opening a message and returning. #56969

Open
3 of 8 tasks
IuliiaHerets opened this issue Feb 17, 2025 · 18 comments
Open
3 of 8 tasks
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor Help Wanted Apply this label when an issue is open to proposals by contributors

Comments

@IuliiaHerets
Copy link

IuliiaHerets commented Feb 17, 2025

If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!


Version Number: 9.0.99-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught on HybridApp, is this reproducible on New Expensify Standalone?: Yes, reproducible on both
Email or phone of affected tester (no customers): [email protected]
Issue reported by: Applause Internal Team
Device used: Motorola MotoG60 - Android 12 - Chrome
App Component: Other

Action Performed:

  1. Open the Expensify app.
  2. Log in with an account with a large amount of chats and messages.
  3. Tap on "Reports"
  4. Tap on the dropdown menu and select "Chats"
  5. Scroll down to the bottom to load all the messages.
  6. Scroll up a bit and open any message.
  7. Return using device back button.
  8. Try to keep scrolling through chats section.
  9. Check the app´s behaviour with this action.

Expected Result:

The user should be able to keep scrolling through the messages on chats section after returning from any opened message.

Actual Result:

"Nothing to show" is displayed on chats section, after the user scrolls to the bottom of the section, opens any message and returns using device back button. User has to return to inbox and reopen "Chats" to see the messages list again.

Workaround:

Unknown

Platforms:

  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug6746011_1739817191453.Nothing.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021891598421702594676
  • Upwork Job ID: 1891598421702594676
  • Last Price Increase: 2025-02-17
Issue OwnerCurrent Issue Owner: @hungvu193
@IuliiaHerets IuliiaHerets added Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 labels Feb 17, 2025
Copy link

melvin-bot bot commented Feb 17, 2025

Triggered auto assignment to @maddylewis (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@maddylewis maddylewis added the External Added to denote the issue can be worked on by a contributor label Feb 17, 2025
@melvin-bot melvin-bot bot changed the title Reports - "Nothing to show" shown on chats, when opening a message and returning. [$250] Reports - "Nothing to show" shown on chats, when opening a message and returning. Feb 17, 2025
Copy link

melvin-bot bot commented Feb 17, 2025

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

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Feb 17, 2025
Copy link

melvin-bot bot commented Feb 17, 2025

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

@linhvovan29546
Copy link
Contributor

linhvovan29546 commented Feb 18, 2025

🚨 Edited by proposal-police: This proposal was edited at 2025-02-18 12:14:34 UTC.

Proposal

Please re-state the problem that we are trying to solve in this issue.

Reports - "Nothing to show" shown on chats, when opening a message and returning

What is the root cause of that problem?

We display the "Nothing to show" message based on the shouldShowEmptyState condition. In this case, shouldShowEmptyState is true, which causes "Nothing to show" to be displayed.

if (shouldShowEmptyState) {
return (
<View style={[shouldUseNarrowLayout ? styles.searchListContentContainerStyles : styles.mt3, styles.flex1]}>
<EmptySearchView
type={type}
hasResults={searchResults.search.hasResults}
/>
</View>
);
}

What causes shouldShowEmptyState to be true?

When scrolling to the end of the list, we handle loading more items using the fetchMoreResults function, which increases the offset. However, in this case, while the API is still fetching, fetchMoreResults continues to be triggered, causing the offset to keep increasing. This happens because shouldShowLoadingMoreItems is false (since the offer count is 0). When the offset becomes larger than the search results, the API returns an empty response, leading to shouldShowEmptyState being true.

const fetchMoreResults = () => {
if (!searchResults?.search?.hasMoreResults || shouldShowLoadingState || shouldShowLoadingMoreItems) {
return;
}
setOffset(offset + CONST.SEARCH.RESULTS_PAGE_SIZE);
};

NOTE: this issue does not relate step 'opening any message'

What changes do you think we should make in order to solve the problem?

We should update the condition for shouldShowLoadingMoreItems to prevent excessive triggering while the API is still fetching data.

const shouldShowLoadingMoreItems = !shouldShowLoadingState && searchResults?.search?.isLoading && searchResults?.search?.offset > 0;

    const shouldShowLoadingMoreItems = !shouldShowLoadingState && searchResults?.search?.isLoading
// Or check if searchResults?.search?.offset >= 0
   const shouldShowLoadingMoreItems = !shouldShowLoadingState && searchResults?.search?.isLoading && searchResults?.search?.offset >= 0; 

Since we updated the shouldShowLoadingMoreItems condition, the SearchRowSkeleton footer now displays when the offset is 0. Therefore, we need to update the listFooterContent condition accordingly.

listFooterContent={
shouldShowLoadingMoreItems ? (
<SearchRowSkeleton
shouldAnimate
fixedNumItems={5}
/>
) : undefined
}

            listFooterContent={
                shouldShowLoadingMoreItems && searchResults?.search?.hasMoreResults ? (
                    <SearchRowSkeleton
                        shouldAnimate
                        fixedNumItems={5}
                    />
                ) : undefined
            }

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

N/A, UI bug

What alternative solutions did you explore? (Optional)

  1. We can update fetchMoreResults to
    https://github.com/Expensify/App/blob/1eb00b066c1da509a1ad5afe19aa4e3c75733b7d/src/components/Search/index.tsx#L449C11-L454
    const fetchMoreResults = () => {
        if (!searchResults?.search?.hasMoreResults || shouldShowLoadingState || shouldShowLoadingMoreItems || searchResults?.search?.isLoading) {
            return;
        }
        setOffset(offset + CONST.SEARCH.RESULTS_PAGE_SIZE);
    };
  1. We can update shouldShowLoadingMoreItems to check the searchResults?.search?.offset >=0

@hungvu193
Copy link
Contributor

@linhvovan29546 I don't think I can reproduce it. My account has ~500 reports but couldn't find a way to reproduce. Do you have any trick or tip to reproduce this issue? Thanks

@linhvovan29546
Copy link
Contributor

linhvovan29546 commented Feb 18, 2025

My account has 100 reports, so I can easily reproduce the issue by continuously scrolling down
Step:

  1. Open the Reports tab.
  2. Scroll down continuously (observe the offset value until it exceeds my report list, then stop scrolling).
  3. The "Nothing to show" message appears.

@hungvu193
Copy link
Contributor

My account has 100 reports, so I can easily reproduce the issue by continuously scrolling down Step:

  1. Open the Reports tab.
  2. Scroll down continuously (observe the offset value until it exceeds my report list, then stop scrolling).
  3. The "Nothing to show" message appears.

Thanks. I can now reproduce but couldn't reproduce it consistently.

Will review the proposal later today.

@linhvovan29546
Copy link
Contributor

Updated proposal #56969 (comment)
Add alternative solutions

@daledah
Copy link
Contributor

daledah commented Feb 19, 2025

Reproducible steps:

Precondition: Account has 50+ chats

  1. Clear cache and restart
  2. Navigate to Reports -> Chats
  3. Scroll down to end
  4. Open a message

OR easier steps:

  1. Navigate to Reports -> Chats
  2. Scroll down to end
  3. Another account send a message to this account.

When receiving new report actions, we perform a Search API call:

SearchActions.search({queryJSON, offset});

With offset is set to 0:

After data is updated, we make changes to offset values:

setOffset(offset + CONST.SEARCH.RESULTS_PAGE_SIZE);

This causes another Search API call:

useEffect(() => {
if (isOffline) {
return;
}
search({queryJSON, offset});
}, [isOffline, offset, queryJSON]);

Because we moved to end of search, increased offset will return empty data:

Image

Because data returned is an empty array, performing Onyx.merge will override object data in Onyx, resulting in "Nothing to show" screen.

Existing proposal is another issue and their solution doesn't fix this issue. We should fix this issue in BE, returning empty object instead of empty array when offset is too high.

Optionally we can fix the failure data in FE here to empty object as well:

data: [],

@linhvovan29546

This comment has been minimized.

@ikevin127
Copy link
Contributor

Proposal

Please re-state the problem that we are trying to solve in this issue

Reports - "Nothing to show" shown on chats, when opening a message and returning.

What is the root cause of that problem?

Note

Note regarding reproducing the issue

I can consistently reproduce with the following steps ⤵
Precondition: Account has 50+ chats.

  1. Settings > Troubleshoot > Clear cache and restart (important to ensure there's no cached data, see videos below).
  2. Navigate to Reports -> Chats.
  3. Scroll down to end in oder to perform at least 2 Search API calls (list expands 2 times - showing older reports, see videos below).
  4. Open a chat report, preferably from the 2nd Search API call batch (older chats).
  5. Navigate back from chat report and observe the Nothing to show UI being displayed.

The reason for seeing the Nothing to show UI comes from the shouldShowEmptyState check being true because of the data.length === 0 check, this happens because when returning back from individual chat report to the Search page, no Search API call is triggered to populate data which is determined here, where the searchresults.data comes from this searchResults check (see in-depth explanation below).

🛑 The main cause comes from this code block which does not work as expected, which is to keep a record of the lastNonEmptySearchResults in order for the chats to be shown upon returning back to the search page after navigating to an individual chat report, without additional Search API calls.

This probably used to work when navigating to an individual chat report was done in a modal, which was keeping the Search component mounted therefore preserving state, therefore the useEffect mentioned above was working as expected.

📓 Since navigation changed a lot, the logic is outdated and when the Search component remounts upon returning from the individual chat report page, we don't have any state data in the lastNonEmptySearchResults variable to show to the user -> resulting in the Nothing to show UI being displayed.

Additionally, this condition is also a cause because currentSearchResults?.data can be an empty object which would make it truthy and return currentSearchResults even though currentSearchResults?.data doesn't have any reports data, instead of returning the lastNonEmptySearchResults.

Image

What changes do you think we should make in order to solve the problem?

🟢 In order to fix the issue according to the Expected result and display the lastNonEmptySearchResults without any extra API calls, just as the original logic (now outdated) intended, my proposal is to use route params to pass the lastNonEmptySearchResults data.

This means that when returning back from the individual chat report, this data will be available right away -> rendering the search list messages just like before the user navigated to the individual chat report.

To do this, we have to implement the following main changes:

  1. Remove this useEffect logic entirely.
  2. In the openReport function which is responsible for navigating the individual report, use the Navigation.setParams() function to pass the backTo and (new) lastNonEmptySearchResults params:
// ...under existing logic
const backTo = Navigation.getActiveRoute();
// ...add setParams
Navigation.setParams({
    backTo,
    ...(Object.keys(currentSearchResults?.data ?? {})?.length > 0 && {lastNonEmptySearchResults: JSON.stringify(currentSearchResults)}),
});
  1. Improve the check of this condition to work as expected (details in RCA):
const searchResults = Object.keys(currentSearchResults?.data ?? {})?.length > 0 ? currentSearchResults : lastNonEmptySearchResults;
  1. Add the following new useEffect at the top of the component where the outdated one was removed:

    See code
    import {useRoute} from '@react-navigation/native';
    import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
    import type {SearchNavigatorParamList} from '@navigation/types';
    import type SCREENS from '@src/SCREENS';
    
    type SearchNavigatorParamList = {
        [SCREENS.SEARCH.ROOT]: {
            backTo?: Routes;
            lastNonEmptySearchResults?: string;
        };
    };
    
    // ...above are imports and type definition
    // ...below is the useEffect logic
    
    const route = useRoute<PlatformStackRouteProp<SearchNavigatorParamList, typeof SCREENS.SEARCH.ROOT>>();
    const parsedLastNonEmptySearchResults = JSON.parse(route.params?.lastNonEmptySearchResults ?? '{}') as SearchResults;
    
    useEffect(() => {
        const parsedLastNonEmptySearchResultsLength = Object.keys(parsedLastNonEmptySearchResults ?? {})?.length;
        const hasCurrentSearchType = currentSearchResults?.search?.type;
    
        if (!parsedLastNonEmptySearchResultsLength || !hasCurrentSearchType) {
            return;
        }
    
        setLastSearchType(currentSearchResults.search.type);
        const isParsedLastNonEmptySearchResultsDataLength = Object.keys(parsedLastNonEmptySearchResults.data ?? {})?.length > 0;
        const isDifferentLastNonEmptySearchResultsLength = Object.keys(lastNonEmptySearchResults?.data ?? {})?.length !== Object.keys(parsedLastNonEmptySearchResults.data ?? {})?.length;
        if (isParsedLastNonEmptySearchResultsDataLength && isDifferentLastNonEmptySearchResultsLength) {
            setLastNonEmptySearchResults(parsedLastNonEmptySearchResults);
        }
    }, [currentSearchResults, lastNonEmptySearchResults, parsedLastNonEmptySearchResults, setLastSearchType]);

🔄 This will ensure that the issue is fixed according to the Expected result by understanding the root cause.

Note

Here's a test branch with all changes for convenience: ikevin127-searchResultsNavigationCache.

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

No need for automated tests since this is related to data cache functionality.

Result videos (before / after)

Android: Native
Before After
before.mp4
after.mp4

@hungvu193
Copy link
Contributor

hungvu193 commented Feb 20, 2025

Still under reviewing

@linhvovan29546
Copy link
Contributor

@hungvu193 It looks like my proposal and steps are related to a different issue. If that's the case, could you help report it? I don't have access to Slack to do so. Thank you!

Precondition: Account has 50+ chats

Action Performed:

  1. Open reports page
  2. Scroll down continuously to the end, and stop after a while.
  3. The "Nothing to show" message appears.

Expected Result:

The list should be displayed.

Actual Result:

The "Nothing to show" message appears after scrolling stops.

Platforms:

Android (Native)

Version Number:

Issue can be reproduced in production.

media_20250220_142714_7736211243490200984.mp4

@hungvu193
Copy link
Contributor

@linhvovan29546 I don't think I can reproduce it, I think you can try to create a post on #expensify-open-source

@linhvovan29546
Copy link
Contributor

@linhvovan29546 I don't think I can reproduce it, I think you can try to create a post on #expensify-open-source

I don't have access to Slack

@hungvu193
Copy link
Contributor

Please request to join slack:

If you haven’t already, check out our contributing guidelines for onboarding and email [email protected] to request to join our Slack channel!

@linhvovan29546
Copy link
Contributor

I've requested before, but I still haven't joined 😔

@hungvu193
Copy link
Contributor

I've requested before, but I still haven't joined 😔

I see. I've just checked, it looks like we have limited guests on slack, but we will be able to add more people soon (next week).

Image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 External Added to denote the issue can be worked on by a contributor Help Wanted Apply this label when an issue is open to proposals by contributors
Projects
None yet
Development

No branches or pull requests

6 participants