Skip to content

Commit

Permalink
Merge pull request #49099 from software-mansion-labs/war-in/fix-app-c…
Browse files Browse the repository at this point in the history
…rash

[HybridApp] Send `completeOnboarding` to OD only on finished request

(cherry picked from commit 4d2d34e)

(CP triggered by AndrewGable)
  • Loading branch information
AndrewGable authored and OSBotify committed Sep 18, 2024
1 parent cd6e715 commit 9c10894
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 80 deletions.
40 changes: 1 addition & 39 deletions src/components/HybridAppMiddleware/index.ios.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,22 @@ import type React from 'react';
import {useEffect} from 'react';
import {NativeEventEmitter, NativeModules} from 'react-native';
import type {NativeModule} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import Log from '@libs/Log';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {useSplashScreenStateContext} from '@src/SplashScreenStateContext';
import type {TryNewDot} from '@src/types/onyx';

type HybridAppMiddlewareProps = {
authenticated: boolean;
children: React.ReactNode;
};

const onboardingStatusSelector = (tryNewDot: OnyxEntry<TryNewDot>) => {
let completedHybridAppOnboarding = tryNewDot?.classicRedirect?.completedHybridAppOnboarding;

if (typeof completedHybridAppOnboarding === 'string') {
completedHybridAppOnboarding = completedHybridAppOnboarding === 'true';
}

return completedHybridAppOnboarding;
};

/*
* HybridAppMiddleware is responsible for handling BootSplash visibility correctly.
* It is crucial to make transitions between OldDot and NewDot look smooth.
* The middleware assumes that the entry point for HybridApp is the /transition route.
*/
function HybridAppMiddleware({children}: HybridAppMiddlewareProps) {
const {setSplashScreenState} = useSplashScreenStateContext();
const [completedHybridAppOnboarding] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT, {selector: onboardingStatusSelector});

/**
* This useEffect tracks changes of `nvp_tryNewDot` value.
* We propagate it from OldDot to NewDot with native method due to limitations of old app.
*/
useEffect(() => {
if (completedHybridAppOnboarding === undefined) {
return;
}

if (!NativeModules.HybridAppModule) {
Log.hmmm(`[HybridApp] Onboarding status has changed, but the HybridAppModule is not defined`);
return;
}

Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true, {completedHybridAppOnboarding});
NativeModules.HybridAppModule.completeOnboarding(completedHybridAppOnboarding);
}, [completedHybridAppOnboarding]);

// In iOS, the HybridApp defines the `onReturnToOldDot` event.
// If we frequently transition from OldDot to NewDot during a single app lifecycle,
// we need to artificially display the bootsplash since the app is booted only once.
// Therefore, isSplashHidden needs to be updated at the appropriate time.
// Therefore, splashScreenState needs to be updated at the appropriate time.
useEffect(() => {
if (!NativeModules.HybridAppModule) {
return;
Expand Down
37 changes: 0 additions & 37 deletions src/components/HybridAppMiddleware/index.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,10 @@
import type React from 'react';
import {useEffect} from 'react';
import {NativeModules} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import Log from '@libs/Log';
import ONYXKEYS from '@src/ONYXKEYS';
import type {TryNewDot} from '@src/types/onyx';

type HybridAppMiddlewareProps = {
children: React.ReactNode;
};

const onboardingStatusSelector = (tryNewDot: OnyxEntry<TryNewDot>) => {
let completedHybridAppOnboarding = tryNewDot?.classicRedirect?.completedHybridAppOnboarding;

if (typeof completedHybridAppOnboarding === 'string') {
completedHybridAppOnboarding = completedHybridAppOnboarding === 'true';
}

return completedHybridAppOnboarding;
};

/*
* HybridAppMiddleware is responsible for handling BootSplash visibility correctly.
* It is crucial to make transitions between OldDot and NewDot look smooth.
* The middleware assumes that the entry point for HybridApp is the /transition route.
*/
function HybridAppMiddleware({children}: HybridAppMiddlewareProps) {
const [completedHybridAppOnboarding] = useOnyx(ONYXKEYS.NVP_TRYNEWDOT, {selector: onboardingStatusSelector});

/**
* This useEffect tracks changes of `nvp_tryNewDot` value.
* We propagate it from OldDot to NewDot with native method due to limitations of old app.
*/
useEffect(() => {
if (completedHybridAppOnboarding === undefined || !NativeModules.HybridAppModule) {
return;
}

Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true, {completedHybridAppOnboarding});
NativeModules.HybridAppModule.completeOnboarding(completedHybridAppOnboarding);
}, [completedHybridAppOnboarding]);

return children;
}

Expand Down
4 changes: 2 additions & 2 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ const WRITE_COMMANDS = {
REOPEN_TASK: 'ReopenTask',
COMPLETE_TASK: 'CompleteTask',
COMPLETE_GUIDED_SETUP: 'CompleteGuidedSetup',
COMPLETE_HYBRID_APP_ONBOARDING: 'CompleteHybridAppOnboarding',
SET_NAME_VALUE_PAIR: 'SetNameValuePair',
SET_REPORT_FIELD: 'Report_SetFields',
DELETE_REPORT_FIELD: 'RemoveReportField',
Expand Down Expand Up @@ -555,7 +554,6 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.REOPEN_TASK]: Parameters.ReopenTaskParams;
[WRITE_COMMANDS.COMPLETE_TASK]: Parameters.CompleteTaskParams;
[WRITE_COMMANDS.COMPLETE_GUIDED_SETUP]: Parameters.CompleteGuidedSetupParams;
[WRITE_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING]: EmptyObject;
[WRITE_COMMANDS.SET_NAME_VALUE_PAIR]: Parameters.SetNameValuePairParams;
[WRITE_COMMANDS.SET_REPORT_FIELD]: Parameters.SetReportFieldParams;
[WRITE_COMMANDS.SET_REPORT_NAME]: Parameters.SetReportNameParams;
Expand Down Expand Up @@ -941,6 +939,7 @@ const SIDE_EFFECT_REQUEST_COMMANDS = {
TWO_FACTOR_AUTH_VALIDATE: 'TwoFactorAuth_Validate',
CONNECT_AS_DELEGATE: 'ConnectAsDelegate',
DISCONNECT_AS_DELEGATE: 'DisconnectAsDelegate',
COMPLETE_HYBRID_APP_ONBOARDING: 'CompleteHybridAppOnboarding',
} as const;

type SideEffectRequestCommand = ValueOf<typeof SIDE_EFFECT_REQUEST_COMMANDS>;
Expand All @@ -959,6 +958,7 @@ type SideEffectRequestCommandParameters = {
[SIDE_EFFECT_REQUEST_COMMANDS.TWO_FACTOR_AUTH_VALIDATE]: Parameters.ValidateTwoFactorAuthParams;
[SIDE_EFFECT_REQUEST_COMMANDS.CONNECT_AS_DELEGATE]: Parameters.ConnectAsDelegateParams;
[SIDE_EFFECT_REQUEST_COMMANDS.DISCONNECT_AS_DELEGATE]: EmptyObject;
[SIDE_EFFECT_REQUEST_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING]: EmptyObject;
};

type ApiRequestCommandParameters = WriteCommandParameters & ReadCommandParameters & SideEffectRequestCommandParameters;
Expand Down
15 changes: 13 additions & 2 deletions src/libs/actions/Welcome/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import {NativeModules} from 'react-native';
import type {OnyxUpdate} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import {WRITE_COMMANDS} from '@libs/API/types';
import {SIDE_EFFECT_REQUEST_COMMANDS} from '@libs/API/types';
import Log from '@libs/Log';
import Navigation from '@libs/Navigation/Navigation';
import variables from '@styles/variables';
import type {OnboardingPurposeType} from '@src/CONST';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type Onboarding from '@src/types/onyx/Onboarding';
Expand Down Expand Up @@ -185,7 +187,16 @@ function completeHybridAppOnboarding() {
},
];

API.write(WRITE_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING, {}, {optimisticData, failureData});
// eslint-disable-next-line rulesdir/no-api-side-effects-method
API.makeRequestWithSideEffects(SIDE_EFFECT_REQUEST_COMMANDS.COMPLETE_HYBRID_APP_ONBOARDING, {}, {optimisticData, failureData}).then((response) => {
if (!response) {
return;
}

// if the call succeeded HybridApp onboarding is finished, otherwise it's not
Log.info(`[HybridApp] Onboarding status has changed. Propagating new value to OldDot`, true, {completedHybridAppOnboarding: response?.jsonCode === CONST.JSON_CODE.SUCCESS});
NativeModules.HybridAppModule.completeOnboarding(response?.jsonCode === CONST.JSON_CODE.SUCCESS);
});
}

Onyx.connect({
Expand Down

0 comments on commit 9c10894

Please sign in to comment.