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] Android – Sign in – Able to dismiss the Onboarding modal using back button #50177

Open
1 of 6 tasks
IuliiaHerets opened this issue Oct 3, 2024 · 31 comments
Open
1 of 6 tasks
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. External Added to denote the issue can be worked on by a contributor Reviewing Has a PR in review Weekly KSv2

Comments

@IuliiaHerets
Copy link

IuliiaHerets commented Oct 3, 2024

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.44-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: https://expensify.testrail.io/index.php?/tests/view/5043083
Email or phone of affected tester (no customers): ponikarchuks+1331024@gmail.com
Issue reported by: Applause Internal Team

Action Performed:

  1. Go to staging app
  2. Log in with a new Gmail account
  3. When Onboarding modal appears tap on Something else
  4. Background the app
  5. Open app and tap back button some times

Expected Result:

Onboarding modal present

Actual Result:

Onboarding modal disappears

Workaround:

Unknown

Platforms:

  • Android: Native
  • Android: mWeb Chrome
  • iOS: Native
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug6623468_1727975678459.And_signin.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021844399665498037051
  • Upwork Job ID: 1844399665498037051
  • Last Price Increase: 2024-10-17
  • Automatic offers:
    • suneox | Reviewer | 104560308
Issue OwnerCurrent Issue Owner: @suneox
@IuliiaHerets IuliiaHerets added Daily KSv2 Bug Something is broken. Auto assigns a BugZero manager. labels Oct 3, 2024
Copy link

melvin-bot bot commented Oct 3, 2024

Triggered auto assignment to @twisterdotcom (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.

@IuliiaHerets
Copy link
Author

@twisterdotcom 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

@layacat
Copy link
Contributor

layacat commented Oct 4, 2024

Proposal

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

Android – Sign in – Able to dismiss the Onboarding modal using back button

What is the root cause of that problem?

We didn't prevent pressing Back button on native platform for OnboardingPersonalDetails screen, so user still able to press back and move to previous screen (home screen).

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

Using the similar approach with OnboardingPurpose screen. We should implement BackHandler for the native platform of OnboardingPersonalDetails and prevent user going back when it's OnboardingPersonalDetails and the ONBOARDING_MODAL_NAVIGATOR stack length is 1 (So it's when OnboardingPersonalDetails is the only stack in the stack).

// OnboardingPersonalDetails/index.native.tsx
 const currentRoute: NavigationPartialRoute | undefined = navigationRef.getCurrentRoute();
 const rootState = navigationRef.getRootState();
 const onboardingNavigatorStackLength = adaptedState.routes.filter(
        (route) => route.name === NAVIGATORS.ONBOARDING_MODAL_NAVIGATOR,
    ).length

    useFocusEffect(
        useCallback(() => {
            // Return true to indicate that the back button press is handled here
            const backAction = () => {
                if (currentRoute?.name === SCREENS.ONBOARDING.PERSONAL_DETAILS && onboardingNavigatorStackLength === 1) {
                    return true;
                }
                return false;
            };

            const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction);

            return () => backHandler.remove();
        }, [currentRoute?.name]),
    );

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

@bernhardoj
Copy link
Contributor

bernhardoj commented Oct 4, 2024

Edited by proposal-police: This proposal was edited at 2024-10-04 05:42:22 UTC.

Proposal

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

User is able to dismiss the onboarding flow on the personal details step.

What is the root cause of that problem?

The onboarding has 3 steps, purpose, work information, and personal details. On the purpose page, we already override the back button to prevent the user from going back.

// To block android native back button behavior
useFocusEffect(
useCallback(() => {
// Return true to indicate that the back button press is handled here
const backAction = () => true;
const backHandler = BackHandler.addEventListener('hardwareBackPress', backAction);
return () => backHandler.remove();
}, []),
);

But this isn't present in either work information or personal details. However, that's not the problem. When going back from the work information or personal details, the user should be going back to the correct step instead of preventing them from going back.

What happens in this issue is, that when we reopen the app, the app will show the last step of the onboarding step, in our case, the personal details step.

function startOnboardingFlow() {
const currentRoute = navigationRef.getCurrentRoute();
const {adaptedState} = getAdaptedStateFromPath(getOnboardingInitialPath(), linkingConfig.config, false);
const focusedRoute = findFocusedRoute(adaptedState as PartialState<NavigationState<RootStackParamList>>);
if (focusedRoute?.name === currentRoute?.name) {
return;
}
navigationRef.resetRoot(adaptedState);

That's possible because of getAdaptedStateFromPath. The result from getAdaptedStateFromPath looks like this (simplified):

{
    routes: [{name: BottomTabNavigator}, {name: OnboardingModalNavigator, state: {routes: [{name: Onboarding_Personal_Details}]}}]
}

So, in the nav stack, only the onboarding personal details page is present. So, when going back, instead of going back to the purpose step, the page is closed.

Why this doesn't happen when we press go back using the in-app back button? That's because we reset the root state which contains the correct state for the onboarding navigator.

function goBack() {
adaptOnboardingRouteState();
Navigation.isNavigationReady().then(() => {
Navigation.goBack();
});
}

function adaptOnboardingRouteState() {
const currentRoute: NavigationPartialRoute | undefined = navigationRef.getCurrentRoute();
if (!currentRoute || currentRoute?.name === SCREENS.ONBOARDING.PURPOSE) {
return;
}
const rootState = navigationRef.getRootState();
const adaptedState = rootState;
const lastRouteIndex = (adaptedState?.routes?.length ?? 0) - 1;
const onBoardingModalNavigatorState = adaptedState?.routes.at(lastRouteIndex)?.state;
if (!onBoardingModalNavigatorState || onBoardingModalNavigatorState?.routes?.length > 1 || lastRouteIndex === -1) {
return;
}
let adaptedOnboardingModalNavigatorState = {} as Readonly<PartialState<NavigationState>>;
if (currentRoute?.name === SCREENS.ONBOARDING.ACCOUNTING && selectedPurpose === CONST.ONBOARDING_CHOICES.MANAGE_TEAM) {
adaptedOnboardingModalNavigatorState = {
index: 2,
routes: [
{
name: SCREENS.ONBOARDING.PURPOSE,
params: currentRoute?.params,
},
{
name: SCREENS.ONBOARDING.EMPLOYEES,
params: currentRoute?.params,
},
{...currentRoute},
],
} as Readonly<PartialState<NavigationState>>;
} else {
adaptedOnboardingModalNavigatorState = {
index: 1,
routes: [
{
name: SCREENS.ONBOARDING.PURPOSE,
params: currentRoute?.params,
},
{...currentRoute},
],
} as Readonly<PartialState<NavigationState>>;
}
const route = adaptedState.routes.at(lastRouteIndex);
if (route) {
route.state = adaptedOnboardingModalNavigatorState;
}
navigationRef.resetRoot(adaptedState);
}

But this solution will cause a brief LHN to be seen.

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

We should improve getAdaptedStateFromPath so that it returns the complete state for the onboarding navigator, then, we won't need adaptOnboardingRouteState anymore. The improvement will be inspired from adaptOnboardingRouteState logic to build the correct routes.

First, create a new function in a separate file called getOnboardingAdaptedState.

export default function getOnboardingAdaptedState(state: PartialState<NavigationState>): PartialState<NavigationState> {
    const onboardingRoute = state.routes[0];
    if (onboardingRoute.name === SCREENS.ONBOARDING.PURPOSE) {
        return state;
    }

    const routes = [];
    if (onboardingRoute.name === SCREENS.ONBOARDING.ACCOUNTING) {
        routes.push({name: SCREENS.ONBOARDING.PURPOSE});
        routes.push({name: SCREENS.ONBOARDING.EMPLOYEES});
        routes.push(onboardingRoute);
    } else {
        routes.push({name: SCREENS.ONBOARDING.PURPOSE});
        routes.push(onboardingRoute);
    }

    return {
        routes,
        index: routes.length - 1,
    }
}

Next, modify the onboarding navigator state here to use the new state from getOnboardingAdaptedState.

if (onboardingModalNavigator) {
routes.push(onboardingModalNavigator);
}

if (onboardingModalNavigator) {
    if (onboardingModalNavigator.state) {
        routes.push({
            ...onboardingModalNavigator,
            state: getOnboardingAdaptedState(onboardingModalNavigator.state),
        });
    } else {
        routes.push(onboardingModalNavigator);
    }
}

Last, we can remove OnboardingFlow.goBack and just use Navigation.goBack.

@allgandalf
Copy link
Contributor

@blazejkustra we fixed this one right!!!!!!!!!!!!!!!!!!!!!!!!!!!! 😮

@melvin-bot melvin-bot bot added the Overdue label Oct 7, 2024
@twisterdotcom
Copy link
Contributor

Sorry, should this be closed or are you saying it's a regression @allgandalf?

@melvin-bot melvin-bot bot added Overdue and removed Overdue labels Oct 7, 2024
@twisterdotcom
Copy link
Contributor

@allgandalf / @blazejkustra I can recreate this, so I'm going to make it external... but let me know if you think this should be handled by somebody specific.

@melvin-bot melvin-bot bot removed the Overdue label Oct 10, 2024
@twisterdotcom twisterdotcom added the External Added to denote the issue can be worked on by a contributor label Oct 10, 2024
@melvin-bot melvin-bot bot changed the title Android – Sign in – Able to dismiss the Onboarding modal using back button [$250] Android – Sign in – Able to dismiss the Onboarding modal using back button Oct 10, 2024
Copy link

melvin-bot bot commented Oct 10, 2024

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

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

melvin-bot bot commented Oct 10, 2024

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

@suneox
Copy link
Contributor

suneox commented Oct 12, 2024

@bernhardoj Your proposal is a potential solution, but could you please update it with the latest main branch and handle the duplicate OnboardingEmployees state issue as well?

Screen.Recording.2024-10-12.at.13.18.17.mp4

@bernhardoj
Copy link
Contributor

Updated my proposal.

handle the duplicate OnboardingEmployees state issue as well?

I can't repro it with my proposal.

@suneox
Copy link
Contributor

suneox commented Oct 13, 2024

I can't repro it with my proposal.

@bernhardoj It still reproduces on my side.

Screen.Recording.2024-10-13.at.18.16.30.mp4

@bernhardoj
Copy link
Contributor

Ah, I think it's the same issue as this one. Can you check if applying the solution there fixes the issue?

@trjExpensify
Copy link
Contributor

👋 @twisterdotcom onboarding related bugs, I'd put those in #convert going forward.

@melvin-bot melvin-bot bot added the Overdue label Oct 16, 2024
@twisterdotcom
Copy link
Contributor

Added to Convert.

@suneox
Copy link
Contributor

suneox commented Oct 16, 2024

Ah, I think it's the same issue as this one. Can you check if applying the solution there fixes the issue?

@bernhardoj The selected proposal from #50064 retains the use of adaptOnboardingRouteState, which will conflict with your solution since it avoids using OnboardingFlow.goBack.

@melvin-bot melvin-bot bot removed the Overdue label Oct 16, 2024
@bernhardoj
Copy link
Contributor

I don't think they will use adaptOnboardingRouteState to solve #50064. What I understand is that they will follow the same pattern of adaptOnboardingRouteState that is using the root state when resetting the root.

Copy link

melvin-bot bot commented Oct 17, 2024

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

Copy link

melvin-bot bot commented Oct 17, 2024

@twisterdotcom @suneox 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!

@twisterdotcom
Copy link
Contributor

@suneox any thoughts on @bernhardoj's response, or are we waiting for more proposals?

@suneox
Copy link
Contributor

suneox commented Oct 18, 2024

@suneox any thoughts on @bernhardoj's response, or are we waiting for more proposals?

I'll check @bernhardoj's response with issue #50064 in few hours

@suneox
Copy link
Contributor

suneox commented Oct 18, 2024

I’ve verified that this issue can be resolved in #50064, so @bernhardoj’s proposal LGTM. Based on the onboarding steps, we will push the missing onboarding route during initialization

🎀 👀 🎀 C+ reviewed

Copy link

melvin-bot bot commented Oct 18, 2024

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

@melvin-bot melvin-bot bot added the Overdue label Oct 21, 2024
@blazejkustra
Copy link
Contributor

@bernhardoj Please tag me on the PR once it's ready 🙏

@bernhardoj
Copy link
Contributor

@blazejkustra sure, @danieldoglas waiting for an assignment

Copy link

melvin-bot bot commented Oct 21, 2024

@danieldoglas, @twisterdotcom, @suneox Uh oh! This issue is overdue by 2 days. Don't forget to update your issues!

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

melvin-bot bot commented Oct 23, 2024

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

Offer link
Upwork job

@melvin-bot melvin-bot bot removed the Overdue label Oct 23, 2024
@danieldoglas
Copy link
Contributor

Assigned.

@melvin-bot melvin-bot bot added Reviewing Has a PR in review Weekly KSv2 and removed Daily KSv2 labels Oct 24, 2024
@bernhardoj
Copy link
Contributor

PR is ready

cc: @suneox @blazejkustra

@adamgrzybowski
Copy link
Contributor

It looks good to me. However, I'm wondering if we want to have the swipe back action possible after freshly opening the app.

e.g. swipe back on the mobile browser ios means go back in history so that would be inconsistent.

If yes then 🟢

If not then I guess we could use a param for the goBack function instead of adding logic to getAdaptedState.

@suneox
Copy link
Contributor

suneox commented Oct 24, 2024

It looks good to me. However, I'm wondering if we want to have the swipe back action possible after freshly opening the app.

e.g. swipe back on the mobile browser ios means go back in history so that would be inconsistent.

I’ve verified that it still works as expected

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. External Added to denote the issue can be worked on by a contributor Reviewing Has a PR in review Weekly KSv2
Projects
Status: No status
Development

No branches or pull requests

10 participants