import { init } from "@sentry/react-native"; import { Component } from "react"; import codePush from "react-native-code-push"; import { BundleState, CODEPUSH_METHOD, SentryConstants, } from "./App/common/constants"; import { logToSentry } from "./App/common/hooks/useSentryLogging"; import { CtaData } from "./App/common/interface"; import RnApp from "./App/common/navigator/RnAppCreator"; import { getBuildConfigDetails, setBuildConfigDetails, } from "./App/common/utilities/CacheUtils"; import { GenericErrorScreen, GenericShimmerScreen, } from "./App/Container/Navi-Insurance"; import { getStringPreference, setStringPreference, } from "./App/common/utilities/SharedPreferenceUtils"; import { useAnalyticsEvent } from "./App/common/hooks/useAnalyticsEvent"; import { EVENT_NAMES, EVENT_PROPERTY_KEYS, EVENT_PROPERTY_VALUES, } from "./App/common/constants"; init({ dsn: SentryConstants.SENTRY_DSN, environment: SentryConstants.SENTRY_ENVIRONMENT_PRODUCTION, }); interface AppState { bundleState: BundleState; } const preloadBundle: string = 'PreloadBundle'; export default class App extends Component<{}, AppState> { constructor(props: {}) { super(props); let bundleState = BundleState.LOADING; getBundleStatus().then(value => (bundleState = value)); this.state = { bundleState: bundleState, }; } checkForUpdates = async () => { let flavor: string | undefined; getBuildConfigDetails().then(res => { flavor = res?.baseUrl; }); await codePush.sync( { installMode: codePush.InstallMode.IMMEDIATE, mandatoryInstallMode: codePush.InstallMode.IMMEDIATE, }, status => { this.onCodepushStatusChange(status); }, ); }; onCodepushStatusChange = (status: codePush.SyncStatus) => { const { sendAsAnalyticsEvent, sendAsGlobalErrorEvent } = useAnalyticsEvent(); 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); logToSentry( `Codepush Ignored | Status: ${status} | MethodName: ${CODEPUSH_METHOD}`, ); break; case codePush.SyncStatus.UNKNOWN_ERROR: this.setState({ bundleState: BundleState.ERROR }); sendAsAnalyticsEvent({ name: EVENT_NAMES.CODEPUSH_FETCH_ERROR, properties: new Map([ [EVENT_PROPERTY_KEYS.STATUS, EVENT_PROPERTY_VALUES.UNKNOWN_ERROR], ]), }); storeBundleStatus(BundleState.ERROR); logToSentry( `Codepush Failed | Status: ${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) { logToSentry( `CtaData is missing or invalid: ${CtaData} | MethodName: getInitialCta`, ); return; } try { const cta = JSON.parse(CtaData) as CtaData; return cta; } catch (error) { logToSentry( `Error parsing CtaData: ${CtaData} | Error: ${error} | MethodName: getInitialCta`, ); return; } }; override componentDidMount(): void { this.checkForUpdates(); setBuildConfigDetails(); } override componentWillUnmount(): void { invalidateStatus(BundleState.LOADING); } override render() { const cta = this.getInitialCta(); if (cta?.title === preloadBundle) { return <>; } return !!cta && this.state.bundleState === BundleState.LOADED ? ( RnApp.create(cta) ) : this.state.bundleState === BundleState.LOADING ? ( ) : ( ); } } const storeBundleStatus = (bundleState: string) => { return setStringPreference("reactBundleState", bundleState); }; const invalidateStatus = (bundleState: string) => { return setStringPreference("reactBundleState", bundleState); }; const getBundleStatus = async () => { return await getStringPreference("reactBundleState", "string"); };