Skip to content

Commit

Permalink
[HybridApp] Clean code (#143)
Browse files Browse the repository at this point in the history
* Simplify HybridApp.ts

* Use early returns

* Rearrange HybridApp module

* Remove redundant keys

* Remove unused import
  • Loading branch information
mateuuszzzzz authored Nov 27, 2024
1 parent 4170968 commit 50c3fed
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 156 deletions.
6 changes: 3 additions & 3 deletions src/components/InitialURLContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type InitialURLContextProviderProps = {
};

function InitialURLContextProvider({children, url, hybridAppSettings}: InitialURLContextProviderProps) {
const [initialURL, setInitialURL] = useState<Route | undefined>(url);
const [initialURL, setInitialURL] = useState<Route | ValueOf<typeof CONST.HYBRID_APP> | undefined>(url);
const [lastVisitedPath] = useOnyx(ONYXKEYS.LAST_VISITED_PATH);
const {splashScreenState, setSplashScreenState} = useSplashScreenStateContext();

Expand Down Expand Up @@ -66,8 +66,8 @@ function InitialURLContextProvider({children, url, hybridAppSettings}: InitialUR

const initialUrlContext = useMemo(
() => ({
initialURL,
setInitialURL,
initialURL: initialURL === CONST.HYBRID_APP.REORDERING_REACT_NATIVE_ACTIVITY_TO_FRONT ? undefined : initialURL,
setInitialURL: setInitialURL as React.Dispatch<React.SetStateAction<Route | undefined>>,
}),
[initialURL],
);
Expand Down
118 changes: 46 additions & 72 deletions src/libs/HybridApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,88 +4,80 @@ import type {OnyxEntry} from 'react-native-onyx';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {Credentials, HybridApp, Session, TryNewDot} from '@src/types/onyx';
import {
setIsSigningIn,
setNewDotSignInState,
setOldDotSignInError,
setOldDotSignInState,
setReadyToShowAuthScreens,
setReadyToSwitchToClassicExperience,
setShouldResetSigningInLogic,
setUseNewDotSignInPage,
} from './actions/HybridApp';
import * as HybridAppActions from './actions/HybridApp';
import type {Init} from './ActiveClientManager/types';
import Log from './Log';

function shouldUseOldApp(tryNewDot?: TryNewDot) {
return tryNewDot?.classicRedirect.dismissed === true;
}

let credentials: OnyxEntry<Credentials>;
Onyx.connect({
key: ONYXKEYS.CREDENTIALS,
callback: (newCredentials) => {
credentials = newCredentials;
},
});

let currentHybridApp: OnyxEntry<HybridApp>;
let currentTryNewDot: OnyxEntry<TryNewDot>;

Onyx.connect({
key: ONYXKEYS.HYBRID_APP,
callback: (hybridApp) => {
console.debug('Last hybridApp value', {hybridApp});
handleSignInFlow(hybridApp, currentTryNewDot);
},
});

Onyx.connect({
key: ONYXKEYS.NVP_TRYNEWDOT,
callback: (tryNewDot) => {
console.debug('Last tryNewDot value', {tryNewDot});
handleSignInFlow(currentHybridApp, tryNewDot);
},
});

let currentSession: OnyxEntry<Session>;
Onyx.connect({
key: ONYXKEYS.SESSION,
callback: (session: OnyxEntry<Session>) => {
if (!currentSession?.authToken && session?.authToken && currentHybridApp?.newDotSignInState === CONST.HYBRID_APP_SIGN_IN_STATE.STARTED) {
HybridAppActions.setNewDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.FINISHED);
}
currentSession = session;
},
});

let credentials: OnyxEntry<Credentials>;
Onyx.connect({
key: ONYXKEYS.CREDENTIALS,
callback: (newCredentials) => {
credentials = newCredentials;
},
});

function shouldUseOldApp(tryNewDot?: TryNewDot) {
return tryNewDot?.classicRedirect.dismissed === true;
}

function handleSignInFlow(hybridApp: OnyxEntry<HybridApp>, tryNewDot: OnyxEntry<TryNewDot>) {
if (!NativeModules.HybridAppModule) {
return;
}

// reset sign in logic
if (hybridApp?.shouldResetSigningInLogic) {
console.log('[HybridApp] Resetting sign in flow');
setReadyToShowAuthScreens(false);
setReadyToSwitchToClassicExperience(false);
setIsSigningIn(false);
setUseNewDotSignInPage(true);
setOldDotSignInError(null);

setOldDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.NOT_STARTED);
setNewDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.NOT_STARTED);
setShouldResetSigningInLogic(false);
return;
}

if (currentHybridApp?.oldDotSignInState === CONST.HYBRID_APP_SIGN_IN_STATE.RETRYING_AFTER_FAILURE && hybridApp?.oldDotSignInState === CONST.HYBRID_APP_SIGN_IN_STATE.FINISHED) {
if (hybridApp?.oldDotSignInError) {
setOldDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.FAILED_AGAIN);
} else {
console.debug('Closing, but why', {currentHybridApp, hybridApp});
NativeModules.HybridAppModule.closeReactNativeApp(false, true);
Log.info('[HybridApp] Unable to open OldDot. Sign-in has failed again');
HybridAppActions.setOldDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.FAILED_AGAIN);
return;
}

Log.info('[HybridApp] Closing NewDot as retrying sign-in to OldDot succeeded');
NativeModules.HybridAppModule.closeReactNativeApp(false, true);
}

console.log('[Hybridapp] should use old app', shouldUseOldApp(tryNewDot));
if (
currentHybridApp?.oldDotSignInState === CONST.HYBRID_APP_SIGN_IN_STATE.STARTED &&
hybridApp?.oldDotSignInState === CONST.HYBRID_APP_SIGN_IN_STATE.FINISHED &&
tryNewDot !== undefined &&
shouldUseOldApp(tryNewDot)
) {
if (hybridApp?.oldDotSignInError) {
Log.info('[HybridApp] Unable to open OldDot. Sign-in has failed');
return;
}
console.log('closing!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');

Log.info('[HybridApp] Closing NewDot as sign-in to OldDot succeeded');
NativeModules.HybridAppModule.closeReactNativeApp(false, false);
}

Expand All @@ -96,50 +88,32 @@ function handleSignInFlow(hybridApp: OnyxEntry<HybridApp>, tryNewDot: OnyxEntry<
credentials?.autoGeneratedPassword &&
tryNewDot !== undefined
) {
if (shouldUseOldApp(tryNewDot)) {
setIsSigningIn(true);
} else {
setReadyToShowAuthScreens(true);
if (!shouldUseOldApp(tryNewDot)) {
Log.info('[HybridApp] The user should see NewDot. There is no need to block the user on the `SignInPage` until the sign-in process is completed on the OldDot side.');
HybridAppActions.setReadyToShowAuthScreens(true);
}

console.log('[HybridApp] signInToOldDot');
setOldDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.STARTED);
NativeModules.HybridAppModule.signInToOldDot(credentials.autoGeneratedLogin, credentials.autoGeneratedPassword);
Log.info(`[HybridApp] Performing sign-in${shouldUseOldApp(tryNewDot) ? '' : ' (in background)'} on OldDot side`);
HybridAppActions.startOldDotSignIn(credentials.autoGeneratedLogin, credentials.autoGeneratedPassword);
}

currentHybridApp = hybridApp;
currentTryNewDot = tryNewDot;
}

let currentSession: OnyxEntry<Session>;
Onyx.connect({
key: ONYXKEYS.SESSION,
callback: (session: OnyxEntry<Session>) => {
if (!currentSession?.authToken && session?.authToken && currentHybridApp?.newDotSignInState === CONST.HYBRID_APP_SIGN_IN_STATE.STARTED) {
setNewDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.FINISHED);
}
currentSession = session;
},
});
function onOldDotSignInFinished(data: string) {
const eventData = JSON.parse(data) as {errorMessage: string};
Log.info(`[HybridApp] onSignInFinished event received`, true, {eventData});
HybridAppActions.finishOldDotSignIn(eventData.errorMessage);
}

const init: Init = () => {
if (!NativeModules.HybridAppModule) {
return;
}

// Setup event listeners
DeviceEventEmitter.addListener(CONST.EVENTS.HYBRID_APP.ON_SIGN_IN_FINISHED, (data) => {
Log.info(`[HybridApp] onSignInFinished event received with data: ${data}`, true);
const eventData = JSON.parse(data as string) as {errorMessage: string};

setIsSigningIn(false);
setOldDotSignInError(eventData.errorMessage);
setOldDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.FINISHED);

if (eventData.errorMessage === null) {
setReadyToSwitchToClassicExperience(true);
}
});
DeviceEventEmitter.addListener(CONST.EVENTS.HYBRID_APP.ON_SIGN_IN_FINISHED, onOldDotSignInFinished);
};

export default {init};
Expand Down
75 changes: 59 additions & 16 deletions src/libs/actions/HybridApp/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import {NativeModules} from 'react-native';
import Onyx from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type CONST from '@src/CONST';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {HybridApp} from '@src/types/onyx';
import type HybridAppSettings from './types';

function parseHybridAppSettings(hybridAppSettings: string): HybridAppSettings {
return JSON.parse(hybridAppSettings) as HybridAppSettings;
}

function setIsSigningIn(isSigningIn: boolean) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {isSigningIn});
}

function setOldDotSignInError(oldDotSignInError: string | null) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {oldDotSignInError});
}
Expand All @@ -20,14 +18,6 @@ function setReadyToShowAuthScreens(readyToShowAuthScreens: boolean) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {readyToShowAuthScreens});
}

function setReadyToSwitchToClassicExperience(readyToSwitchToClassicExperience: boolean) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {readyToSwitchToClassicExperience});
}

function setShouldResetSigningInLogic(shouldResetSigningInLogic: boolean) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {shouldResetSigningInLogic});
}

function setUseNewDotSignInPage(useNewDotSignInPage: boolean) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {useNewDotSignInPage});
}
Expand All @@ -44,15 +34,68 @@ function setOldDotSignInState(oldDotSignInState: ValueOf<typeof CONST.HYBRID_APP
Onyx.merge(ONYXKEYS.HYBRID_APP, {oldDotSignInState});
}

function resetHybridAppSignInState() {
Onyx.merge(ONYXKEYS.HYBRID_APP, {
readyToShowAuthScreens: false,
useNewDotSignInPage: true,
oldDotSignInError: null,
oldDotSignInState: CONST.HYBRID_APP_SIGN_IN_STATE.NOT_STARTED,
newDotSignInState: CONST.HYBRID_APP_SIGN_IN_STATE.NOT_STARTED,
});
}

function startOldDotSignIn(autoGeneratedLogin: string, autoGeneratedPassword: string) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {
oldDotSignInState: CONST.HYBRID_APP_SIGN_IN_STATE.STARTED,
});

NativeModules.HybridAppModule.signInToOldDot(autoGeneratedLogin, autoGeneratedPassword);
}

function retryOldDotSignInAfterFailure(autoGeneratedLogin: string, autoGeneratedPassword: string) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {
oldDotSignInError: null,
oldDotSignInState: CONST.HYBRID_APP_SIGN_IN_STATE.RETRYING_AFTER_FAILURE,
});

NativeModules.HybridAppModule.signInToOldDot(autoGeneratedLogin, autoGeneratedPassword);
}

function finishOldDotSignIn(errorMessage: string | null) {
Onyx.merge(ONYXKEYS.HYBRID_APP, {
oldDotSignInError: errorMessage,
oldDotSignInState: CONST.HYBRID_APP_SIGN_IN_STATE.FINISHED,
});
}

function prepareHybridAppAfterTransitionToNewDot(hybridApp: HybridApp) {
if (hybridApp?.useNewDotSignInPage) {
return Onyx.merge(ONYXKEYS.HYBRID_APP, {
...hybridApp,
readyToShowAuthScreens: false,
oldDotSignInError: null,
oldDotSignInState: CONST.HYBRID_APP_SIGN_IN_STATE.NOT_STARTED,
newDotSignInState: CONST.HYBRID_APP_SIGN_IN_STATE.NOT_STARTED,
});
}

return Onyx.merge(ONYXKEYS.HYBRID_APP, {
...hybridApp,
readyToShowAuthScreens: true,
});
}

export {
parseHybridAppSettings,
setOldDotSignInError,
setIsSigningIn,
setReadyToShowAuthScreens,
setReadyToSwitchToClassicExperience,
setShouldResetSigningInLogic,
setUseNewDotSignInPage,
setLoggedOutFromOldDot,
setNewDotSignInState,
setOldDotSignInState,
resetHybridAppSignInState,
retryOldDotSignInAfterFailure,
finishOldDotSignIn,
startOldDotSignIn,
prepareHybridAppAfterTransitionToNewDot,
};
30 changes: 5 additions & 25 deletions src/libs/actions/Session/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,7 @@ import * as App from '@userActions/App';
import {KEYS_TO_PRESERVE, openApp} from '@userActions/App';
import {KEYS_TO_PRESERVE_DELEGATE_ACCESS} from '@userActions/Delegate';
import * as Device from '@userActions/Device';
import {
parseHybridAppSettings,
setLoggedOutFromOldDot,
setNewDotSignInState,
setOldDotSignInState,
setReadyToShowAuthScreens,
setReadyToSwitchToClassicExperience,
setUseNewDotSignInPage,
} from '@userActions/HybridApp';
import * as HybridAppActions from '@userActions/HybridApp';
import * as PriorityMode from '@userActions/PriorityMode';
import redirectToSignIn from '@userActions/SignInRedirect';
import Timing from '@userActions/Timing';
Expand Down Expand Up @@ -490,31 +482,21 @@ function signUpUser() {
}

function signInAfterTransitionFromOldDot(route: Route, hybridAppSettings: string) {
const parsedHybridAppSettings = parseHybridAppSettings(hybridAppSettings);
const parsedHybridAppSettings = HybridAppActions.parseHybridAppSettings(hybridAppSettings);
const {initialOnyxValues} = parsedHybridAppSettings;
const {hybridApp, ...newDotOnyxValues} = initialOnyxValues;

const clearOnyxBeforeSignIn = () => {
if (!hybridApp.useNewDotSignInPage) {
setReadyToShowAuthScreens(true);
setReadyToSwitchToClassicExperience(true);
return Promise.resolve();
}

return Onyx.clear();
};

const initAppAfterTransition = () => {
if (hybridApp.useNewDotSignInPage) {
setNewDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.NOT_STARTED);
setOldDotSignInState(CONST.HYBRID_APP_SIGN_IN_STATE.NOT_STARTED);
}
return Promise.resolve();
};

return new Promise<Route>((resolve) => {
clearOnyxBeforeSignIn()
.then(() => Onyx.merge(ONYXKEYS.HYBRID_APP, hybridApp))
.then(() => HybridAppActions.prepareHybridAppAfterTransitionToNewDot(hybridApp))
.then(() => Onyx.multiSet(newDotOnyxValues))
.then(() => {
if (!hybridApp.shouldRemoveDelegatedAccess) {
Expand All @@ -523,11 +505,9 @@ function signInAfterTransitionFromOldDot(route: Route, hybridAppSettings: string
return Onyx.clear(KEYS_TO_PRESERVE_DELEGATE_ACCESS);
})
.then(() => {
// This data is mocked and should be returned by BeginSignUp/SignInUser API commands
setUseNewDotSignInPage(!!hybridApp.useNewDotSignInPage);
setLoggedOutFromOldDot(!!hybridApp.loggedOutFromOldDot);
HybridAppActions.setUseNewDotSignInPage(!!hybridApp.useNewDotSignInPage);
HybridAppActions.setLoggedOutFromOldDot(!!hybridApp.loggedOutFromOldDot);
})
.then(initAppAfterTransition)
.catch((error) => {
Log.hmmm('[HybridApp] Initialization of HybridApp has failed. Forcing transition', {error});
})
Expand Down
Loading

0 comments on commit 50c3fed

Please sign in to comment.