TP-60588 | Code push loading screen
This commit is contained in:
61
App.tsx
61
App.tsx
@@ -10,7 +10,13 @@ import {
|
||||
StatusBar,
|
||||
type Permission,
|
||||
} from 'react-native';
|
||||
import { default as codePush, default as CodePush } from 'react-native-code-push';
|
||||
import {
|
||||
default as codePush,
|
||||
default as CodePush,
|
||||
DownloadProgress,
|
||||
DownloadProgressCallback,
|
||||
SyncStatusChangedCallback,
|
||||
} from 'react-native-code-push';
|
||||
import { Provider } from 'react-redux';
|
||||
import { PersistGate } from 'redux-persist/integration/react';
|
||||
import store, { persistor } from './src/store/store';
|
||||
@@ -44,6 +50,7 @@ import { setJsErrorHandler } from './src/services/exception-handler.service';
|
||||
import fetchUpdatedRemoteConfig from './src/services/firebaseFetchAndUpdate.service';
|
||||
import { StorageKeys } from './src/types/storageKeys';
|
||||
import { setCurrentScreenName } from 'react-native-clarity';
|
||||
import CodePushLoadingModal, { CodePushLoadingModalRef } from './CodePushModal';
|
||||
|
||||
initSentry();
|
||||
|
||||
@@ -56,17 +63,28 @@ LogBox.ignoreAllLogs();
|
||||
|
||||
export let GlobalDocumentMap: Record<string, TDocumentObj | string> = {};
|
||||
|
||||
async function checkCodePushAndSync() {
|
||||
async function checkCodePushAndSync(
|
||||
onSyncStatusChange: SyncStatusChangedCallback,
|
||||
onDownloadProgress: DownloadProgressCallback
|
||||
) {
|
||||
try {
|
||||
await CodePush.sync({
|
||||
installMode: codePush.InstallMode.IMMEDIATE,
|
||||
});
|
||||
await CodePush.sync(
|
||||
{
|
||||
installMode: codePush.InstallMode.IMMEDIATE,
|
||||
},
|
||||
onSyncStatusChange,
|
||||
onDownloadProgress
|
||||
);
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function handleAppStateChange(nextAppState: any) {
|
||||
function handleAppStateChange(
|
||||
nextAppState: any,
|
||||
onSyncStatusChange: SyncStatusChangedCallback,
|
||||
onDownloadProgress: DownloadProgressCallback
|
||||
) {
|
||||
if (nextAppState == 'active') {
|
||||
checkCodePushAndSync();
|
||||
checkCodePushAndSync(onSyncStatusChange, onDownloadProgress);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +92,8 @@ const PERMISSION_CHECK_POLL_INTERVAL = 5 * MILLISECONDS_IN_A_SECOND;
|
||||
|
||||
function App() {
|
||||
const [permissions, setPermissions] = React.useState(true);
|
||||
const modalRef = React.useRef<CodePushLoadingModalRef>(null);
|
||||
|
||||
const askForPermissions = async () => {
|
||||
const permissionsToRequest = await getPermissionsToRequest();
|
||||
if (Platform.OS === 'android') {
|
||||
@@ -94,6 +114,28 @@ function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const onSyncStatusChange = (syncStatus: codePush.SyncStatus) => {
|
||||
switch (syncStatus) {
|
||||
case codePush.SyncStatus.DOWNLOADING_PACKAGE:
|
||||
modalRef.current?.show();
|
||||
break;
|
||||
case codePush.SyncStatus.INSTALLING_UPDATE:
|
||||
break;
|
||||
case codePush.SyncStatus.UP_TO_DATE:
|
||||
modalRef.current?.hide();
|
||||
break;
|
||||
default:
|
||||
modalRef.current?.hide();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const onDownloadProgress = (downloadProgress: DownloadProgress) => {
|
||||
if (downloadProgress) {
|
||||
modalRef.current?.updateProgress(downloadProgress);
|
||||
}
|
||||
};
|
||||
|
||||
const getActiveRouteName = (state) => {
|
||||
if (!state || typeof state.index !== 'number') {
|
||||
return 'Unknown';
|
||||
@@ -126,7 +168,7 @@ function App() {
|
||||
fetchUpdatedRemoteConfig();
|
||||
askForPermissions();
|
||||
const appStateChange = AppState.addEventListener('change', async (change) => {
|
||||
handleAppStateChange(change);
|
||||
handleAppStateChange(change, onSyncStatusChange, onDownloadProgress);
|
||||
hydrateGlobalImageMap();
|
||||
});
|
||||
(async () => {
|
||||
@@ -136,7 +178,7 @@ function App() {
|
||||
GlobalDocumentMap = parsedData;
|
||||
}
|
||||
})();
|
||||
checkCodePushAndSync();
|
||||
checkCodePushAndSync(onSyncStatusChange, onDownloadProgress);
|
||||
setForegroundTimeStampAndClickstream();
|
||||
|
||||
return () => {
|
||||
@@ -166,6 +208,7 @@ function App() {
|
||||
<ErrorBoundary>{permissions ? <AuthRouter /> : <Permissions />}</ErrorBoundary>
|
||||
</NavigationContainer>
|
||||
<ToastContainer config={toastConfigs} position="top" topOffset={18} />
|
||||
<CodePushLoadingModal ref={modalRef} />
|
||||
</PersistGate>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
92
CodePushModal.tsx
Normal file
92
CodePushModal.tsx
Normal file
@@ -0,0 +1,92 @@
|
||||
import { COLORS } from '@rn-ui-lib/colors';
|
||||
import ProgressBar from './ProgressBar';
|
||||
import React, { forwardRef, useImperativeHandle, useState } from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import { DownloadProgress } from 'react-native-code-push';
|
||||
import ModalWrapperForAlfredV2 from '@common/ModalWrapperForAlfredV2';
|
||||
import LottieView from 'lottie-react-native';
|
||||
import Text from '@rn-ui-lib/components/Text';
|
||||
import NaviLogoWithTextIcon from '@rn-ui-lib/icons/NaviLogoWithTextIcon';
|
||||
|
||||
export interface CodePushLoadingModalRef {
|
||||
show: () => void;
|
||||
hide: () => void;
|
||||
updateProgress: (progress: DownloadProgress) => void;
|
||||
}
|
||||
|
||||
const CodePushLoadingModal = forwardRef<CodePushLoadingModalRef>((_, ref) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [progress, setProgress] = useState<DownloadProgress>();
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
show: () => setVisible(true),
|
||||
hide: () => setVisible(false),
|
||||
updateProgress: (downloadProgress: DownloadProgress) => setProgress(downloadProgress),
|
||||
}));
|
||||
|
||||
const getInMb = (progress: number) => {
|
||||
if (progress) return `${(progress / 1024 / 1024).toFixed(2)} MB`;
|
||||
return '-';
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalWrapperForAlfredV2 visible={visible} animationType="fade">
|
||||
<View style={styles.modalContainer}>
|
||||
<View style={styles.modalContent}>
|
||||
<View style={{ alignItems: 'center', marginBottom: 24 }}>
|
||||
<LottieView
|
||||
style={{ width: 140, height: 140 }}
|
||||
source={require('./loader.json')}
|
||||
autoPlay
|
||||
loop
|
||||
/>
|
||||
</View>
|
||||
|
||||
|
||||
{progress ? (
|
||||
<View>
|
||||
<Text style={styles.header}>Updating to a newer version...</Text>
|
||||
<ProgressBar progress={progress?.receivedBytes / progress?.totalBytes} />
|
||||
<Text style={styles.progressText}>
|
||||
{getInMb(progress?.receivedBytes)} / {getInMb(progress?.totalBytes)}
|
||||
</Text>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<NaviLogoWithTextIcon />
|
||||
</View>
|
||||
</View>
|
||||
</ModalWrapperForAlfredV2>
|
||||
);
|
||||
});
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
modalContainer: {
|
||||
flex: 1,
|
||||
padding: 20,
|
||||
},
|
||||
modalContent: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
header: {
|
||||
fontSize: 14,
|
||||
color: COLORS.TEXT.BLACK_24,
|
||||
paddingTop: 24,
|
||||
paddingBottom: 6,
|
||||
},
|
||||
progressText: {
|
||||
color: COLORS.TEXT.BLACK_24,
|
||||
fontSize: 14,
|
||||
fontWeight: '700',
|
||||
marginTop: 6,
|
||||
},
|
||||
progressBar: {
|
||||
width: '100%',
|
||||
height: 2,
|
||||
marginTop: 10,
|
||||
},
|
||||
});
|
||||
|
||||
export default CodePushLoadingModal;
|
||||
43
ProgressBar.tsx
Normal file
43
ProgressBar.tsx
Normal file
@@ -0,0 +1,43 @@
|
||||
import { COLORS } from '@rn-ui-lib/colors';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { View, Text, Animated, StyleSheet } from 'react-native';
|
||||
|
||||
const ProgressBar = ({ progress, height = 10, color = '#18bf5f'}) => {
|
||||
const [animatedWidth] = useState(new Animated.Value(0));
|
||||
|
||||
console.log({progress})
|
||||
useEffect(() => {
|
||||
Animated.timing(animatedWidth, {
|
||||
toValue: progress * 100,
|
||||
duration: 500,
|
||||
useNativeDriver: false,
|
||||
}).start();
|
||||
}, [progress]);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, { height }]}>
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.fill,
|
||||
{ width: animatedWidth.interpolate({
|
||||
inputRange: [0, 100],
|
||||
outputRange: ['0%', '100%'],
|
||||
}), backgroundColor: color },
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: '#e0e0e0',
|
||||
borderRadius: 8,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
fill: {
|
||||
height: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
export default ProgressBar;
|
||||
1
loader.json
Normal file
1
loader.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user