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

[HOLD for payment 2025-01-13] [$250] Add spinning loader until full list of policies is successfully download on the client #52766

Closed
JmillsExpensify opened this issue Nov 19, 2024 · 41 comments
Assignees
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Daily KSv2 External Added to denote the issue can be worked on by a contributor NewFeature Something to build that is a new item.

Comments

@JmillsExpensify
Copy link

JmillsExpensify commented Nov 19, 2024

Problem
In the scenario where an OpenApp call still hasn't successfully finished, we confusingly show the workspace empty state, prompting users to create a new workspace as if they didn't have any.

CleanShot 2024-11-19 at 13 47 29@2x

Solution
Let's add a loading spinner or where an empty state (or a list of workspaces) would otherwise be.

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021859258055635274316
  • Upwork Job ID: 1859258055635274316
  • Last Price Increase: 2024-12-04
  • Automatic offers:
    • twilight2294 | Contributor | 105210527
Issue OwnerCurrent Issue Owner: @JmillsExpensify
@JmillsExpensify JmillsExpensify added Daily KSv2 Internal Requires API changes or must be handled by Expensify staff NewFeature Something to build that is a new item. labels Nov 19, 2024
@JmillsExpensify JmillsExpensify self-assigned this Nov 19, 2024
Copy link

melvin-bot bot commented Nov 19, 2024

Current assignee @JmillsExpensify is eligible for the NewFeature assigner, not assigning anyone new.

@melvin-bot melvin-bot bot added Weekly KSv2 and removed Daily KSv2 labels Nov 19, 2024
@JmillsExpensify
Copy link
Author

Keeping internal until we align on the right solution.

@dannymcclain
Copy link
Contributor

we previously landed on a spinner given that you could have no workspaces vs potentially some. Does that still feel like the right approach, or should we go with a skeleton loader?

I still like the spinner. Skeletons make sense to me when we know exactly what the UI is going to look like, but I find the transition from a skeleton loader to a big empty state card (for example) to be pretty jarring.

@twilight2294
Copy link
Contributor

twilight2294 commented Nov 19, 2024

Edited by proposal-police: This proposal was edited at 2024-12-04 17:15:04 UTC.

Proposal

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

Add spinning loader until full list of policies is successfully download on the client

What is the root cause of that problem?

Feature request, we currently directly show the empty workspace component if there are no policies:

if (isEmptyObject(workspaces)) {
return (
<ScreenWrapper

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

We need to show a loading spinner if the OpenApp has no response yet, to do so in WorkspacesListPage, we should get the onyxkey IS_LOADING_APP and then show a activity spinner if the user is not offline and the data is loading:

    const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP);
    const isLoading  = !isOffline && isLoadingApp;

then before the following:

if (isEmptyObject(workspaces)) {
return (
<ScreenWrapper

We need to add:

    if(isLoading) {
        return(
        
                <ActivityIndicator
                    size={CONST.ACTIVITY_INDICATOR_SIZE.LARGE}
                    style={styles.flex1}
                    color={theme.spinner}
                />
          
        )
    }

Note that we can skip the isOffline check if the user is offline and the api call is still in process, in such case we would show the user loader untill the user is online, that can be discussed further.
We can also add a additional check for onyx collection policies:

const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);

We can also update the isLoading condition to also check if policies are loaded completely.

we also need to update WorkspaceSwitcherPage to show this loading state:

    const WorkspaceCardCreateAWorkspaceInstance = isLoadingApp ? <FullScreenLoadingIndicator  /> : <WorkspaceCardCreateAWorkspace />;

Style changes will be made during PR phase

Result video

Screen.Recording.2024-11-20.at.1.37.01.AM.mov

@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels Nov 19, 2024
@shawnborton
Copy link
Contributor

and then you’re going to need to click Inbox > #admins to get back where you were.

Totally agree with Danny there. I like the spinner.

@twilight2294
Copy link
Contributor

twilight2294 commented Nov 19, 2024

Proposal updated

Added result video

@Krishna2323
Copy link
Contributor

Krishna2323 commented Nov 19, 2024

Edited by proposal-police: This proposal was edited at 2024-12-04 16:59:29 UTC.

Proposal


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

Add spinning loader until full list of policies is successfully download on the client

What is the root cause of that problem?

Improvement

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


  • We should get the app loading state from useOnyx(ONYXKEYS.IS_LOADING_APP).
const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP);
  • Then conditionally render FullScreenLoadingIndicator instead of FeatureList when isLoadingApp is true.
    <ScrollView contentContainerStyle={styles.pt3}>
    <View style={[styles.flex1, isLessThanMediumScreen ? styles.workspaceSectionMobile : styles.workspaceSection]}>
    <FeatureList
                // We can also remove "styles.pt3" when "isLoadingApp" is true.
                <ScrollView contentContainerStyle={[styles.pt3, isLoadingApp && styles.h100]}>
                    <View style={[styles.flex1, isLessThanMediumScreen || isLoadingApp ? styles.workspaceSectionMobile : styles.workspaceSection]}>
                        {!isLoadingApp ? (
                            <FeatureList
                                menuItems={workspaceFeatures}
                                title={translate('workspace.emptyWorkspace.title')}
                                subtitle={translate('workspace.emptyWorkspace.subtitle')}
                                ctaText={translate('workspace.new.newWorkspace')}
                                ctaAccessibilityLabel={translate('workspace.new.newWorkspace')}
                                onCtaPress={() => interceptAnonymousUser(() => App.createWorkspaceWithPolicyDraftAndNavigateToIt())}
                                illustration={LottieAnimations.WorkspacePlanet}
                                // We use this style to vertically center the illustration, as the original illustration is not centered
                                illustrationStyle={styles.emptyWorkspaceIllustrationStyle}
                                titleStyles={styles.textHeadlineH1}
                            />
                        ) : (
                            <FullScreenLoadingIndicator style={[styles.flex1, styles.pRelative]} />
                        )}
                    </View>
                </ScrollView>
  • In WorkspaceSwitcherPage, we can update WorkspaceCardCreateAWorkspaceInstance value to return FullScreenLoadingIndicator when isLoadingApp is true.
    const WorkspaceCardCreateAWorkspaceInstance = isLoadingApp ? <FullScreenLoadingIndicator style={[styles.flex1, styles.pRelative]} /> : <WorkspaceCardCreateAWorkspace />;

<SelectionList<WorkspaceListItem>
ListItem={UserListItem}
sections={sections}
onSelectRow={(option) => selectPolicy(option.policyID)}
textInputLabel={usersWorkspaces.length >= CONST.STANDARD_LIST_ITEM_LIMIT ? translate('common.search') : undefined}
textInputValue={searchTerm}
onChangeText={setSearchTerm}
headerMessage={headerMessage}
listEmptyContent={WorkspaceCardCreateAWorkspaceInstance}
shouldShowListEmptyContent={shouldShowCreateWorkspace}
initiallyFocusedOptionKey={activeWorkspaceID ?? CONST.WORKSPACE_SWITCHER.NAME}
showLoadingPlaceholder={fetchStatus.status === 'loading' || !didScreenTransitionEnd}
showConfirmButton={!!activeWorkspaceID}
shouldUseDefaultTheme
confirmButtonText={translate('workspace.common.clearFilter')}
onConfirm={() => selectPolicy(undefined)}
/>

What alternative solutions did you explore? (Optional)

Result

Monosnap.screencast.2024-11-20.02-08-54.mp4

@JmillsExpensify JmillsExpensify added the External Added to denote the issue can be worked on by a contributor label Nov 20, 2024
@melvin-bot melvin-bot bot changed the title Add spinning loader until full list of policies is successfully download on the client [$250] Add spinning loader until full list of policies is successfully download on the client Nov 20, 2024
Copy link

melvin-bot bot commented Nov 20, 2024

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

@melvin-bot melvin-bot bot added the Help Wanted Apply this label when an issue is open to proposals by contributors label Nov 20, 2024
Copy link

melvin-bot bot commented Nov 20, 2024

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

@JmillsExpensify
Copy link
Author

Opened this up for proposals and I will also update the original post with the spinner solution.

@JmillsExpensify JmillsExpensify removed the Internal Requires API changes or must be handled by Expensify staff label Nov 20, 2024
@mkzie2
Copy link
Contributor

mkzie2 commented Nov 21, 2024

Edited by proposal-police: This proposal was edited at 2024-12-04 16:50:08 UTC.

Proposal

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

Add spinning loader until full list of policies is successfully download on the client

What is the root cause of that problem?

New feature

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

The workspace's empty state can confuse in some cases

  • When OpenApp API isn't complete
  • When ReconnectApp API isn't complete
  1. So we need to get ONYXKEYS.IS_LOADING_REPORT_DATA which will be true in both cases OpenApp and ReconnectApp API is called. An important point is we need to set initialValue: true if not the workspace list page can flicker if we reload the page
const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA, {initialValue: true});
  1. If isLoadingReportData is true, display the spinner instead of FeatureList here
<ScrollView contentContainerStyle={[styles.pt3, isLoadingReportData && styles.flex1]}>
    <View style={[styles.flex1, isLessThanMediumScreen || isLoadingReportData ? styles.workspaceSectionMobile : styles.workspaceSection]}>
        {isLoadingReportData ? (
            <FullScreenLoadingIndicator style={[styles.flex1]} />
        ) : (
            <FeatureList
                menuItems={workspaceFeatures}
                title={translate('workspace.emptyWorkspace.title')}
                subtitle={translate('workspace.emptyWorkspace.subtitle')}
                ctaText={translate('workspace.new.newWorkspace')}
                ctaAccessibilityLabel={translate('workspace.new.newWorkspace')}
                onCtaPress={() => interceptAnonymousUser(() => App.createWorkspaceWithPolicyDraftAndNavigateToIt())}
                illustration={LottieAnimations.WorkspacePlanet}
                // We use this style to vertically center the illustration, as the original illustration is not centered
                illustrationStyle={styles.emptyWorkspaceIllustrationStyle}
                titleStyles={styles.textHeadlineH1}
            />
        )}
    </View>
</ScrollView>

We also need to do the same in WorkspaceSwitcherPage

{isLoadingReportData ? (
    <FullScreenLoadingIndicator style={[styles.flex1]} />
) : (
    <<SelectionList<WorkspaceListItem>
)}

<SelectionList<WorkspaceListItem>

OPTIONAL: If we always want to show the spinner while OpenApp is calling even if the policy list isn't empty, we can add the
FullScreenLoadingIndicator here if isLoadingReportData is true. otherwise, display this content.

{shouldUseNarrowLayout && <View style={[styles.pl5, styles.pr5]}>{getHeaderButton()}</View>}
<FlatList

What alternative solutions did you explore? (Optional)

If we only want to display the spinner while the OpenApp API is calling, for point 1, we can get data from the ONYXKEYS.IS_LOADING_APP key and still need to configure initialValue to be true.

const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP, {initialValue: true});

@parasharrajat
Copy link
Member

Reviewing proposals...

Copy link

melvin-bot bot commented Nov 26, 2024

@JmillsExpensify, @parasharrajat Whoops! This issue is 2 days overdue. Let's get this updated quick!

@melvin-bot melvin-bot bot added the Overdue label Nov 26, 2024
@garrettmknight garrettmknight moved this to Bugs and Follow Up Issues in [#whatsnext] #expense Nov 26, 2024
@JmillsExpensify
Copy link
Author

How's the proposal review going?

@melvin-bot melvin-bot bot removed the Help Wanted Apply this label when an issue is open to proposals by contributors label Dec 5, 2024
Copy link

melvin-bot bot commented Dec 5, 2024

📣 @twilight2294 🎉 An offer has been automatically sent to your Upwork account for the Contributor role 🎉 Thanks for contributing to the Expensify app!

Offer link
Upwork job
Please accept the offer 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 📖

@parasharrajat
Copy link
Member

@JmillsExpensify Do you want to show the loader while user is offline and workspace is not yet loaded?

@JmillsExpensify Bump on this question?

@twilight2294
Copy link
Contributor

I will make a draft PR today until we wait for the answer @parasharrajat

@twilight2294
Copy link
Contributor

bump @JmillsExpensify for the question here

@twilight2294
Copy link
Contributor

bump @JmillsExpensify

@melvin-bot melvin-bot bot added the Overdue label Dec 14, 2024
@JmillsExpensify
Copy link
Author

Apologies for the delay. No I don't think we want to show the spinner while the user is offline.

@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Weekly KSv2 Overdue labels Dec 17, 2024
@melvin-bot melvin-bot bot added Weekly KSv2 Awaiting Payment Auto-added when associated PR is deployed to production and removed Weekly KSv2 labels Jan 6, 2025
@melvin-bot melvin-bot bot changed the title [$250] Add spinning loader until full list of policies is successfully download on the client [HOLD for payment 2025-01-13] [$250] Add spinning loader until full list of policies is successfully download on the client Jan 6, 2025
Copy link

melvin-bot bot commented Jan 6, 2025

Reviewing label has been removed, please complete the "BugZero Checklist".

@melvin-bot melvin-bot bot removed the Reviewing Has a PR in review label Jan 6, 2025
Copy link

melvin-bot bot commented Jan 6, 2025

The solution for this issue has been 🚀 deployed to production 🚀 in version 9.0.80-6 and is now subject to a 7-day regression period 📆. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2025-01-13. 🎊

For reference, here are some details about the assignees on this issue:

Copy link

melvin-bot bot commented Jan 6, 2025

BugZero Checklist: The PR adding this new feature has been merged! The following checklist (instructions) will need to be completed before the issue can be closed:

  • [@parasharrajat] Please propose regression test steps to ensure the new feature will work correctly on production in further releases.
  • [@JmillsExpensify] Link the GH issue for creating/updating the regression test once above steps have been agreed upon.

@garrettmknight garrettmknight moved this from Bugs and Follow Up Issues to Hold for Payment in [#whatsnext] #expense Jan 7, 2025
@melvin-bot melvin-bot bot added Daily KSv2 and removed Weekly KSv2 labels Jan 13, 2025
@JmillsExpensify
Copy link
Author

Payment summary:

@JmillsExpensify
Copy link
Author

Contributor paid out. @parasharrajat please complete the BZ checklist before requesting payment. I'll circle back for any regression test plus approval.

@github-project-automation github-project-automation bot moved this from Hold for Payment to Done in [#whatsnext] #expense Jan 13, 2025
@parasharrajat
Copy link
Member

Regression Test Steps

Test 1:
Precondition: Be on 3G / Slow internet
  1. Go to the Troubleshoot page in settings > Click "Clear cache and restart"
  2. Go to Workspaces.
  3. Verify that: you will see a loading spinner before seeing the workspace list page / empty workspace screen
Test 2:
Precondition: Be on 3G / Slow internet
  1. Go to the Troubleshoot page in settings > Click "Clear cache and restart"
  2. Go to Workspace switcher LHP
  3. Verify that: you will see a loading spinner before seeing the workspace list page / create workspace screen

Do you agree 👍 or 👎 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Awaiting Payment Auto-added when associated PR is deployed to production Daily KSv2 External Added to denote the issue can be worked on by a contributor NewFeature Something to build that is a new item.
Projects
Status: Done
Development

No branches or pull requests

8 participants