import { Component } from "react"; import codePush from "react-native-code-push"; import { GenericErrorScreen } from "./App/Container/Navi-Insurance"; import { AnalyticsEventNameConstants, BundleState, CODEPUSH_METHOD, EVENT_NAMES, EVENT_PROPERTY_KEYS, EVENT_PROPERTY_VALUES, } from "./App/common/constants"; import { sendAsAnalyticsEvent } from "./App/common/hooks/useAnalyticsEvent"; import { CtaData } from "./App/common/interface"; import RnApp from "./App/common/navigator/RnAppCreator"; import { getBuildConfigDetailsFromCta, setBuildConfigDetailsFromCta, } from "./App/common/utilities/CacheUtils"; import { initSentry } from "./App/common/utilities/SentryUtils"; import { getStringPreference, setStringPreference, } from "./App/common/utilities/SharedPreferenceUtils"; interface AppState { bundleState: BundleState; } const preloadBundle: string = "PreloadBundle"; export default class App extends Component<{}, AppState> { constructor(props: {}) { super(props); initSentry(getBuildConfigDetailsFromCta(this.getInitialCta()!!).flavor); let bundleState = BundleState.LOADING; getBundleStatus().then(value => (bundleState = value)); this.state = { bundleState: bundleState, }; } checkForUpdates = async () => { const cta = this.getInitialCta(); await setBuildConfigDetailsFromCta(cta!!); await codePush.sync( { installMode: cta?.title === preloadBundle ? codePush.InstallMode.IMMEDIATE : codePush.InstallMode.ON_NEXT_RESTART, mandatoryInstallMode: codePush.InstallMode.IMMEDIATE, }, status => { this.onCodepushStatusChange(status); }, ); }; onCodepushStatusChange = (status: codePush.SyncStatus) => { switch (status) { case codePush.SyncStatus.CHECKING_FOR_UPDATE: case codePush.SyncStatus.DOWNLOADING_PACKAGE: case codePush.SyncStatus.INSTALLING_UPDATE: this.setState({ bundleState: BundleState.LOADING }); storeBundleStatus(BundleState.LOADING); break; case codePush.SyncStatus.UP_TO_DATE: this.setState({ bundleState: BundleState.LOADED }); storeBundleStatus(BundleState.LOADED); break; case codePush.SyncStatus.UPDATE_IGNORED: this.setState({ bundleState: BundleState.LOADED }); storeBundleStatus(BundleState.LOADED); sendAsAnalyticsEvent({ name: AnalyticsEventNameConstants.HI_RN_CODEPUSH_ERROR, properties: { errorType: EVENT_NAMES.CODEPUSH_IGNORED_ERROR, error: `${status}`, methodName: `${CODEPUSH_METHOD}`, }, }); break; case codePush.SyncStatus.UNKNOWN_ERROR: this.setState({ bundleState: BundleState.ERROR }); sendAsAnalyticsEvent({ name: EVENT_NAMES.CODEPUSH_FETCH_ERROR, properties: { [EVENT_PROPERTY_KEYS.STATUS]: EVENT_PROPERTY_VALUES.UNKNOWN_ERROR, }, }); sendAsAnalyticsEvent({ name: AnalyticsEventNameConstants.HI_RN_CODEPUSH_ERROR, properties: { errorType: EVENT_NAMES.CODEPUSH_FAILED_ERROR, error: `${status}`, methodName: `${CODEPUSH_METHOD}`, }, }); break; default: this.setState({ bundleState: BundleState.LOADED }); storeBundleStatus(BundleState.LOADED); } }; override shouldComponentUpdate( nextProps: Readonly<{}>, nextState: Readonly, _: any, ): boolean { return this.state.bundleState !== nextState.bundleState; } getInitialCta = (): CtaData | undefined => { const { CtaData } = this.props as any; if (!CtaData) { sendAsAnalyticsEvent({ name: AnalyticsEventNameConstants.HI_INVALID_SCREEN_CTA, properties: { errorType: EVENT_NAMES.CTA_MISSING_ERROR, error: `${CtaData}`, methodName: "getInitialCta", }, }); return; } try { const cta = JSON.parse(CtaData) as CtaData; return cta; } catch (error) { sendAsAnalyticsEvent({ name: AnalyticsEventNameConstants.HI_INVALID_SCREEN_CTA, properties: { errorType: EVENT_NAMES.CTA_PARSING_ERROR, error: `${error}`, methodName: "getInitialCta", }, }); return; } }; override componentDidMount(): void { this.checkForUpdates(); } override componentWillUnmount(): void { invalidateStatus(BundleState.LOADING); } override render() { const cta = this.getInitialCta(); if (cta?.title === preloadBundle) { return <>; } else if (!!cta) { return RnApp.create(cta); } else { sendAsAnalyticsEvent({ name: EVENT_NAMES.INVALID_SCREEN_CTA, }); return ; } } } const storeBundleStatus = (bundleState: string) => { return setStringPreference("reactBundleState", bundleState); }; const invalidateStatus = (bundleState: string) => { return setStringPreference("reactBundleState", bundleState); }; const getBundleStatus = async () => { return await getStringPreference("reactBundleState", "string"); };