TP-67100 | Fetch Bundle Immediately (#10937)

This commit is contained in:
Mayank Singh
2024-05-21 12:07:06 +05:30
committed by GitHub
parent e3322539ea
commit 6b87974097
6 changed files with 290 additions and 7 deletions

73
App.tsx
View File

@@ -1,7 +1,7 @@
import { init } from "@sentry/react-native";
import { Component } from "react";
import codePush from "react-native-code-push";
import { SentryConstants } from "./App/common/constants/SentryConstants";
import { BundleState, 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";
@@ -9,13 +9,30 @@ import {
getBuildConfigDetails,
setBuildConfigDetails,
} from "./App/common/utilities/CacheUtils";
import { GenericShimmerScreen } from "./App/Container/Navi-Insurance";
import {
getStringPreference,
setStringPreference,
} from "./App/common/utilities/SharedPreferenceUtils";
init({
dsn: SentryConstants.SENTRY_DSN,
environment: SentryConstants.SENTRY_ENVIRONMENT_PRODUCTION,
});
export default class App extends Component<{}> {
interface AppState {
bundleState: BundleState;
}
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 => {
@@ -34,18 +51,44 @@ export default class App extends Component<{}> {
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);
logToSentry(
`Codepush Ignored | Status: ${status} | MethodName: onCodepushStatusChange`,
);
break;
case codePush.SyncStatus.UNKNOWN_ERROR:
this.setState({ bundleState: BundleState.ERROR });
storeBundleStatus(BundleState.ERROR);
logToSentry(
`Codepush Failed | Status: ${status} | MethodName: onCodepushStatusChange`,
);
break;
default:
this.setState({ bundleState: BundleState.LOADED });
storeBundleStatus(BundleState.LOADED);
}
};
override shouldComponentUpdate(
nextProps: Readonly<{}>,
nextState: Readonly<AppState>,
_: any,
): boolean {
return this.state.bundleState !== nextState.bundleState;
}
getInitialCta = (): CtaData | undefined => {
const { CtaData } = this.props as any;
@@ -68,12 +111,34 @@ export default class App extends Component<{}> {
};
override componentDidMount(): void {
setBuildConfigDetails();
this.checkForUpdates();
setBuildConfigDetails();
}
override componentWillUnmount(): void {
invalidateStatus(BundleState.LOADING);
}
override render() {
const cta = this.getInitialCta();
return cta ? RnApp.create(cta) : <></>;
return !!cta && this.state.bundleState === BundleState.LOADED ? (
RnApp.create(cta)
) : this.state.bundleState === BundleState.LOADING ? (
<GenericShimmerScreen />
) : (
<></>
);
}
}
const storeBundleStatus = (bundleState: string) => {
return setStringPreference("reactBundleState", bundleState);
};
const invalidateStatus = (bundleState: string) => {
return setStringPreference("reactBundleState", bundleState);
};
const getBundleStatus = async () => {
return await getStringPreference("reactBundleState", "string");
};

View File

@@ -1,3 +1,4 @@
export { default as QuoteOfferScreen } from "./screen/quote-offer-screen/QuoteOfferScreen";
export { default as QuoteApologyScreen } from "./screen/quote-apology-screen/QuoteApologyScreen";
export { default as ComparePlanScreen } from "./screen/compare-plan-screen/ComparePlanScreen";
export { default as ComparePlanScreen } from "./screen/compare-plan-screen/ComparePlanScreen";
export { default as GenericShimmerScreen } from "./screen/generic-shimmer-screen/GenericShimmerScreen";

View File

@@ -0,0 +1,104 @@
import { View } from "react-native";
import SkeletonPlaceholder from "react-native-skeleton-placeholder";
import Colors from "../../../../../assets/colors/colors";
import styles from "./GenericShimmerScreenStyle";
import { StaticHeader } from "../../../../../components/reusable/static-header/StaticHeader";
import { CtaData, CtaType } from "../../../../common/interface";
import { ConstantCta } from "../../../../common/constants/CtaConstants";
import { logToSentry } from "../../../../common/hooks/useSentryLogging";
import {
invalidateCacheWithUrl,
shouldInvalidateSavedData,
} from "../../../../common/utilities/CacheUtils";
import { NativeDeeplinkNavigatorModule } from "../../../../common/native-module/NativeModules";
const GenericShimmerScreen = () => {
const handleClick = (cta?: CtaData) => {
if (!cta) {
logToSentry(
`Navigation cta is missing or invalid: ${cta} | MethodName: handleClick}`,
);
return;
}
if (invalidateCacheWithUrl(cta.url) || shouldInvalidateSavedData(cta)) {
invalidatePostApiData();
}
try {
switch (cta.type) {
case CtaType.DEEP_LINK:
case CtaType.USE_ROOT_DEEPLINK_NAVIGATOR:
NativeDeeplinkNavigatorModule.navigateToNaviInsuranceDeeplinkNavigator(
JSON.stringify(cta),
);
break;
default:
NativeDeeplinkNavigatorModule.navigateToNaviDeeplinkNavigator(
JSON.stringify(cta),
);
break;
}
} catch (error) {
logToSentry(
`Error while navigating to deep link with CTA: ${cta} | MethodName: handleClick}`,
);
}
};
return (
<View style={styles.container}>
<View style={styles.header}>
<StaticHeader
handleClick={handleClick}
leftIconCta={ConstantCta.STATIC_HEADER_LEFT_ICON_CTA}
/>
</View>
<ContentShimmer />
<FooterShimmer />
</View>
);
};
export default GenericShimmerScreen;
const ContentShimmer = () => {
return (
<View style={styles.content}>
<SkeletonPlaceholder
backgroundColor={Colors.shimmerBgColor}
highlightColor={Colors.shimmerHighlightColor}
direction="right"
angle={100}
borderRadius={4}
>
<View>
<View style={styles.shimmerLayout1} />
<View style={styles.shimmerLayout2} />
<View style={styles.shimmerLayout3} />
<View style={styles.shimmerLayout4} />
</View>
</SkeletonPlaceholder>
</View>
);
};
const FooterShimmer = () => {
return (
<View style={styles.footer}>
<SkeletonPlaceholder
backgroundColor={Colors.shimmerBgColor}
highlightColor={Colors.shimmerHighlightColor}
direction="right"
angle={100}
borderRadius={4}
>
<View>
<View style={styles.shimmerFooterLayout} />
</View>
</SkeletonPlaceholder>
</View>
);
};
function invalidatePostApiData() {
throw new Error("Function not implemented.");
}

View File

@@ -0,0 +1,108 @@
import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
shimmerHeader: {
alignItems: "stretch",
position: "absolute",
zIndex: 1,
},
shimmerContent: {},
shimmerFooterContainer: {
height: 100,
zIndex: 2,
position: "absolute",
bottom: 0,
},
container: {
flex: 1,
flexDirection: "column",
justifyContent: "center",
},
header: {
position: "absolute",
top: 0,
width: "100%",
backgroundColor: "white",
},
content: {
marginTop: 88,
flexGrow: 1,
marginHorizontal: 16,
},
footer: {
borderTopStartRadius: 16,
borderTopEndRadius: 16,
shadowColor: "black",
shadowOpacity: 0.26,
shadowOffset: { width: 0, height: 2 },
shadowRadius: 10,
elevation: 3,
backgroundColor: "white",
},
shimmerLayout1: {
position: "relative",
marginTop: 12,
height: 152,
alignItems: "center",
borderRadius: 4,
flexShrink: 0,
gap: 10.5,
},
shimmerLayout2: {
position: "relative",
marginTop: 24,
height: 78,
alignItems: "center",
borderRadius: 4,
flexShrink: 0,
gap: 10.5,
},
shimmerLayout3: {
position: "relative",
marginTop: 24,
height: 148,
alignItems: "center",
borderRadius: 4,
flexShrink: 0,
gap: 10.5,
},
shimmerLayout4: {
position: "relative",
marginTop: 24,
height: 35,
alignItems: "center",
borderRadius: 4,
flexShrink: 0,
gap: 10.5,
},
shimmerFooterLayout: {
position: "relative",
marginHorizontal: 16,
marginTop: 16,
marginBottom: 24,
height: 49,
alignItems: "center",
borderRadius: 4,
flexShrink: 0,
gap: 10.5,
},
shimmerHeaderLayout: {
position: "relative",
marginHorizontal: 16,
marginTop: 16,
marginBottom: 24,
height: 49,
alignItems: "center",
borderRadius: 4,
flexShrink: 0,
gap: 10.5,
},
});
export default styles;

View File

@@ -25,6 +25,12 @@ export enum ScreenProperties {
ANIMATE_HEADER = "ANIMATE_HEADER",
}
export enum BundleState {
LOADING = "LOADING",
LOADED = "LOADED",
ERROR = "ERROR",
}
export const ERROR_TITLE = "Something went wrong";
export const ERROR_SUBTITLE = "Please try again after some time";
export const RETRY = "Retry";

View File

@@ -1,5 +1,4 @@
import { TouchableOpacity } from "react-native-gesture-handler";
import { BackHandler, View } from "react-native";
import { BackHandler, View, TouchableOpacity } from "react-native";
import { CtaData } from "../../../App/common/interface";
import { styles } from "./StaticHeaderStyle";
import { ImageName } from "../../../App/common/constants/StringConstant";