UNPKG

react-native-app-update-helper

Version:
525 lines (524 loc) 18.8 kB
"use strict"; import { useEffect, useState } from 'react'; import { Text, TouchableOpacity, View, StyleSheet, Dimensions, Image, Platform, Modal, Linking } from 'react-native'; import AppUpdatedOverlay from "./components/AppUpdatedOverlay.js"; import { getStoredValue, storeValue } from "./components/store.js"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; const { width } = Dimensions.get('window'); const alert = require('./alertImage.png'); const AVAILABLE_UPDATE_STORAGE_KEY = 'o2bY6kS6bTUAFNZD'; const STORED_VERSION_UPDATE_KEY = 'nDUM3KXAwqQDR9KA'; export const AutoUpdateOverlay = ({ currentVersion, iosStoreLink, androidStoreLink, icon = alert, mainTitle = 'Update Available', description = 'Please update the application to the latest version.', buttonTitle = 'Update', isWhatsNewRequired = true, whatsNewDescription, primaryColor = '#11B8B2', backgroundColor = '#EEEEEE', titleFontFamily, descriptionFontFamily, buttonTitleFontFamily, titleFontSize = 24, descriptionFontSize = 14, buttonTitleFontSize = 14 }) => { const [autoDetectedVersionNeedsUpdate, setAutoDetectedVersionNeedsUpdate] = useState(false); const [isUpdateAvailable, setIsUpdateAvailable] = useState(null); const [isAppUpdated, setIsAppUpdated] = useState(false); const [whatsNewContent, setWhatsNewContent] = useState(''); const [latestVersion, setLatestVersion] = useState(''); const fetchGooglePlayVersion = async () => { try { const googlePlayResponse = await fetch(androidStoreLink); const googlePlayText = await googlePlayResponse.text(); const googlePlayVersionMatch = googlePlayText.match(/\[\[\["([\d.]+?)"\]\]/); if (googlePlayVersionMatch && googlePlayVersionMatch[1]) { const latestVersion = googlePlayVersionMatch[1].trim(); const currentVersionParts = currentVersion.split('.').map(Number); const latestVersionParts = latestVersion.split('.').map(Number); setLatestVersion(latestVersion); for (let i = 0; i < Math.max(currentVersionParts.length, latestVersionParts.length); i++) { const currentPart = currentVersionParts[i] || 0; const latestPart = latestVersionParts[i] || 0; if (currentPart < latestPart) { if (i == 2) { const shown = await getStoredValue({ storageTag: AVAILABLE_UPDATE_STORAGE_KEY }); if (shown == null) { await storeValue({ storageTag: AVAILABLE_UPDATE_STORAGE_KEY, valueToStore: 'shown' }); setIsUpdateAvailable(true); setAutoDetectedVersionNeedsUpdate(true); } else { setAutoDetectedVersionNeedsUpdate(false); } } else { setIsUpdateAvailable(false); setAutoDetectedVersionNeedsUpdate(true); } return; } else if (currentPart > latestPart) { setAutoDetectedVersionNeedsUpdate(false); setIsUpdateAvailable(false); return; } } setAutoDetectedVersionNeedsUpdate(false); setIsUpdateAvailable(false); } } catch (error) { console.error('Error fetching Google Play Store version:', error); } }; const fetchAppStoreVersion = async () => { try { const appStoreResponse = await fetch(iosStoreLink); const appStoreText = await appStoreResponse.text(); const appStoreVersionMatch = appStoreText.match(/Version\s([\d.]+)/); if (appStoreVersionMatch && appStoreVersionMatch[1]) { const latestVersion = appStoreVersionMatch[1].trim(); const currentVersionParts = currentVersion.split('.').map(Number); const latestVersionParts = latestVersion.split('.').map(Number); setLatestVersion(latestVersion); for (let i = 0; i < Math.max(currentVersionParts.length, latestVersionParts.length); i++) { const currentPart = currentVersionParts[i] || 0; const latestPart = latestVersionParts[i] || 0; if (currentPart < latestPart) { if (i == 2) { const shown = await getStoredValue({ storageTag: AVAILABLE_UPDATE_STORAGE_KEY }); if (shown == null) { await storeValue({ storageTag: AVAILABLE_UPDATE_STORAGE_KEY, valueToStore: 'shown' }); setIsUpdateAvailable(true); setAutoDetectedVersionNeedsUpdate(true); } else { setAutoDetectedVersionNeedsUpdate(false); } } else { setIsUpdateAvailable(false); setAutoDetectedVersionNeedsUpdate(true); } return; } else if (currentPart > latestPart) { setAutoDetectedVersionNeedsUpdate(false); setIsUpdateAvailable(false); return; } } setAutoDetectedVersionNeedsUpdate(false); setIsUpdateAvailable(false); } } catch (error) { console.error('Error fetching App Store version:', error); } }; const fetchWhatsNew = async () => { if (Platform.OS == 'android') { const googlePlayResponse = await fetch(androidStoreLink); const googlePlayText = await googlePlayResponse.text(); const description = googlePlayText.match(/<div itemprop="description">(.*?)<\/div>/s); if (description && description[1]) { setWhatsNewContent(description[1]); setIsAppUpdated(true); } } else { const appStoreResponse = await fetch(iosStoreLink); const appStoreText = await appStoreResponse.text(); const descriptionSection = appStoreText.match(/<div class="we-truncate we-truncate--multi-line we-truncate--interactive " dir>([\s\S]*?)<\/div>/gi); if (descriptionSection && descriptionSection[0]) { const description = descriptionSection[0].match(/<p dir="false" data-test-bidi>([\s\S]*?)<\/p>/i); if (description && description[1]) { setWhatsNewContent(description[1]); setIsAppUpdated(true); } } } }; const checkIfUserUpdated = async () => { try { const storedVersion = await getStoredValue({ storageTag: STORED_VERSION_UPDATE_KEY }); if (storedVersion !== null) { if (storedVersion == currentVersion) { setIsAppUpdated(false); } else { await storeValue({ storageTag: STORED_VERSION_UPDATE_KEY, valueToStore: currentVersion }); if (whatsNewDescription) { setWhatsNewContent(whatsNewDescription); setIsAppUpdated(true); } else { fetchWhatsNew(); } } } else { await storeValue({ storageTag: STORED_VERSION_UPDATE_KEY, valueToStore: currentVersion }); } } catch (e) { console.log(e, 'Error story current version'); } }; const onDownloadButtonPress = () => { Linking.openURL(Platform.OS == 'ios' ? iosStoreLink : androidStoreLink); }; useEffect(() => { if (Platform.OS == 'ios') { fetchAppStoreVersion(); } else { fetchGooglePlayVersion(); } if (isWhatsNewRequired) { checkIfUserUpdated(); } }, [currentVersion, iosStoreLink, androidStoreLink, isWhatsNewRequired]); return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx(Modal, { visible: autoDetectedVersionNeedsUpdate, transparent: true, animationType: "slide", onRequestClose: () => { setAutoDetectedVersionNeedsUpdate(false); }, children: /*#__PURE__*/_jsx(View, { style: [styles.centeredView, { backgroundColor: backgroundColor }], children: /*#__PURE__*/_jsxs(View, { style: styles.modalView, children: [/*#__PURE__*/_jsx(Image, { source: icon, style: styles.icon }), /*#__PURE__*/_jsx(Text, { style: [styles.mainTitle, { fontFamily: titleFontFamily ? titleFontFamily : undefined, fontSize: titleFontSize }], children: mainTitle }), /*#__PURE__*/_jsx(Text, { style: [styles.description, { fontFamily: descriptionFontFamily ? descriptionFontFamily : undefined, fontSize: descriptionFontSize, lineHeight: descriptionFontSize + 2 }], children: description }), /*#__PURE__*/_jsxs(_Fragment, { children: [!isUpdateAvailable && /*#__PURE__*/_jsx(TouchableOpacity, { style: [styles.button, { backgroundColor: primaryColor }], onPress: onDownloadButtonPress, children: /*#__PURE__*/_jsx(Text, { style: [styles.buttonTitle, { fontFamily: buttonTitleFontFamily ? buttonTitleFontFamily : undefined, fontSize: buttonTitleFontSize }], children: buttonTitle }) }), isUpdateAvailable && /*#__PURE__*/_jsxs(View, { style: styles.buttonsContainer, children: [/*#__PURE__*/_jsx(TouchableOpacity, { style: [styles.button, { backgroundColor: primaryColor }], onPress: onDownloadButtonPress, children: /*#__PURE__*/_jsx(Text, { style: [styles.buttonTitle, { fontFamily: buttonTitleFontFamily ? buttonTitleFontFamily : undefined, fontSize: buttonTitleFontSize }], children: "Update" }) }), /*#__PURE__*/_jsx(TouchableOpacity, { style: [styles.button, styles.dismissButton], onPress: () => setAutoDetectedVersionNeedsUpdate(false), children: /*#__PURE__*/_jsx(Text, { style: [styles.buttonTitle, styles.dismissButtonTitle, { fontFamily: buttonTitleFontFamily ? buttonTitleFontFamily : undefined, color: primaryColor, fontSize: buttonTitleFontSize }], children: "Skip for now" }) })] })] })] }) }) }), isWhatsNewRequired && isAppUpdated ? /*#__PURE__*/_jsx(AppUpdatedOverlay, { content: whatsNewContent, version: latestVersion, primaryColor: primaryColor, backgroundColor: backgroundColor, titleFontFamily: titleFontFamily, descriptionFontFamily: descriptionFontFamily, buttonTitleFontFamily: buttonTitleFontFamily, titleFontSize: titleFontSize, descriptionFontSize: descriptionFontSize, buttonTitleFontSize: buttonTitleFontSize }) : /*#__PURE__*/_jsx(_Fragment, {})] }); }; export const ManualUpdateOverlay = ({ updateAvailable = false, currentVersion, iosStoreLink, androidStoreLink, icon = alert, mainTitle = 'Update Available', description = 'Please update the application to the latest version.', buttonTitle = 'Update', primaryColor = '#11B8B2', backgroundColor = '#EEEEEE', isWhatsNewRequired = true, isMandatoryUpdate, whatsNewDescription, onDismissButtonPress, titleFontFamily, descriptionFontFamily, buttonTitleFontFamily, titleFontSize = 24, descriptionFontSize = 14, buttonTitleFontSize = 14 }) => { const [isAppUpdated, setIsAppUpdated] = useState(false); const [whatsNewContent, setWhatsNewContent] = useState(''); const fetchWhatsNew = async () => { if (Platform.OS == 'android') { const googlePlayResponse = await fetch(androidStoreLink); const googlePlayText = await googlePlayResponse.text(); const description = googlePlayText.match(/<div itemprop="description">(.*?)<\/div>/s); if (description && description[1]) { setWhatsNewContent(description[1]); setIsAppUpdated(true); } } else { const appStoreResponse = await fetch(iosStoreLink); const appStoreText = await appStoreResponse.text(); const descriptionSection = appStoreText.match(/<div class="we-truncate we-truncate--multi-line we-truncate--interactive " dir>([\s\S]*?)<\/div>/gi); if (descriptionSection && descriptionSection[0]) { const description = descriptionSection[0].match(/<p dir="false" data-test-bidi>([\s\S]*?)<\/p>/i); if (description && description[1]) { setWhatsNewContent(description[1]); setIsAppUpdated(true); } } } }; const checkIfUserUpdated = async () => { try { const storedVersion = await getStoredValue({ storageTag: STORED_VERSION_UPDATE_KEY }); if (storedVersion !== null) { if (storedVersion == currentVersion) { setIsAppUpdated(false); } else { await storeValue({ storageTag: STORED_VERSION_UPDATE_KEY, valueToStore: currentVersion }); if (whatsNewDescription) { setWhatsNewContent(whatsNewDescription); setIsAppUpdated(true); } else { fetchWhatsNew(); } } } else { await storeValue({ storageTag: STORED_VERSION_UPDATE_KEY, valueToStore: currentVersion }); } } catch (e) { console.log(e, 'Error story current version'); } }; const onDownloadButtonPress = () => { Linking.openURL(Platform.OS == 'ios' ? iosStoreLink : androidStoreLink); }; useEffect(() => { if (isWhatsNewRequired) { checkIfUserUpdated(); } }, [currentVersion, iosStoreLink, androidStoreLink, whatsNewDescription, isWhatsNewRequired]); return /*#__PURE__*/_jsxs(_Fragment, { children: [/*#__PURE__*/_jsx(Modal, { visible: updateAvailable, transparent: true, animationType: "slide", onRequestClose: () => { onDismissButtonPress(); }, children: /*#__PURE__*/_jsx(View, { style: [styles.centeredView, { backgroundColor: backgroundColor }], children: /*#__PURE__*/_jsxs(View, { style: styles.modalView, children: [/*#__PURE__*/_jsx(Image, { source: icon, style: styles.icon }), /*#__PURE__*/_jsx(Text, { style: [styles.mainTitle, { fontFamily: titleFontFamily ? titleFontFamily : undefined, fontSize: titleFontSize }], children: mainTitle }), /*#__PURE__*/_jsx(Text, { style: [styles.description, { fontFamily: descriptionFontFamily ? descriptionFontFamily : undefined, fontSize: descriptionFontSize, lineHeight: descriptionFontSize + 2 }], children: description }), isMandatoryUpdate && /*#__PURE__*/_jsx(TouchableOpacity, { style: [styles.button, { backgroundColor: primaryColor }], onPress: onDownloadButtonPress, children: /*#__PURE__*/_jsx(Text, { style: [styles.buttonTitle, { fontFamily: buttonTitleFontFamily ? buttonTitleFontFamily : undefined, fontSize: buttonTitleFontSize }], children: buttonTitle }) }), !isMandatoryUpdate && /*#__PURE__*/_jsxs(View, { style: styles.buttonsContainer, children: [/*#__PURE__*/_jsx(TouchableOpacity, { style: [styles.button, { backgroundColor: primaryColor }], onPress: onDownloadButtonPress, children: /*#__PURE__*/_jsx(Text, { style: [styles.buttonTitle, { fontFamily: buttonTitleFontFamily ? buttonTitleFontFamily : undefined, fontSize: buttonTitleFontSize }], children: "Update" }) }), /*#__PURE__*/_jsx(TouchableOpacity, { style: [styles.button, styles.dismissButton], onPress: onDismissButtonPress, children: /*#__PURE__*/_jsx(Text, { style: [styles.buttonTitle, styles.dismissButtonTitle, { fontFamily: buttonTitleFontFamily ? buttonTitleFontFamily : undefined, color: primaryColor, fontSize: buttonTitleFontSize }], children: "Skip for now" }) })] })] }) }) }), isWhatsNewRequired && isAppUpdated ? /*#__PURE__*/_jsx(AppUpdatedOverlay, { content: whatsNewContent, version: currentVersion, primaryColor: primaryColor, backgroundColor: backgroundColor, titleFontFamily: titleFontFamily, descriptionFontFamily: descriptionFontFamily, buttonTitleFontFamily: buttonTitleFontFamily, titleFontSize: titleFontSize, descriptionFontSize: descriptionFontSize, buttonTitleFontSize: buttonTitleFontSize }) : /*#__PURE__*/_jsx(_Fragment, {})] }); }; const mainStyles = { color: { title: '#14202B', text: '#9B9B9B', placeholder: '#a0a0a0', white: '#FFFFFF' }, fontSize: { title: 20, small: 12 }, borderRadius: { main: 25, small: 8, extraSmall: 4 } }; const styles = StyleSheet.create({ centeredView: { flex: 1, justifyContent: 'center', alignItems: 'center' }, modalView: { position: 'absolute', bottom: 0, width: width, backgroundColor: 'white', padding: 35, paddingBottom: 20, alignItems: 'center', justifyContent: 'center' }, icon: { height: 64, width: 64, marginBottom: 20 }, mainTitle: { color: mainStyles.color.title, fontSize: mainStyles.fontSize.title, textAlign: 'center', marginBottom: 20 }, description: { color: mainStyles.color.text, fontSize: mainStyles.fontSize.small, textAlign: 'center', width: width / 1.2, lineHeight: 24, marginBottom: 30 }, button: { width: width - 40, paddingVertical: 15, paddingHorizontal: 20, borderRadius: mainStyles.borderRadius.extraSmall, marginBottom: 10 }, dismissButton: { backgroundColor: 'transparent' }, buttonTitle: { color: mainStyles.color.white, fontSize: mainStyles.fontSize.small, textAlign: 'center' }, dismissButtonTitle: { color: mainStyles.color.text }, buttonsContainer: { alignItems: 'center' } }); //# sourceMappingURL=index.js.map