Skip to content

Instantly share code, notes, and snippets.

@gregfenton
Created January 12, 2022 15:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregfenton/8016611542ffb3c3fb7629ffea0e778b to your computer and use it in GitHub Desktop.
Save gregfenton/8016611542ffb3c3fb7629ffea0e778b to your computer and use it in GitHub Desktop.
An "about app" page that displays various Expo constants
import React, {useContext, useState} from 'react';
import {StyleSheet, Dimensions, View, Platform} from 'react-native';
import {List, Button, Text} from 'react-native-paper';
import * as Sentry from '@sentry/react-native';
import * as Updates from 'expo-updates';
import Constants from 'expo-constants';
import {
widthPercentageToDP as wPct,
heightPercentageToDP as hPct,
} from 'react-native-responsive-screen';
import {useTranslation} from 'react-i18next';
import AccordionList from '../../app/components/AccordionList';
import * as MiscConstants from '../../app/common/constants/misc';
const UPDATE_NOT_CHECKED = -1;
const UPDATE_HAVE_LATEST = 0;
const UPDATE_NEWER_AVAILABLE = 1;
const AboutAppView = () => {
const [updateAvail, setUpdateAvail] = useState(UPDATE_NOT_CHECKED);
const [updatedManifest, setUpdatedManifest] = useState({});
const {width: scrWidth, height: scrHeight} = Dimensions.get('screen');
const styles = getStyles(scrWidth, scrHeight);
const {t} = useTranslation();
const checkForUpdate = async () => {
try {
let response = await Updates.checkForUpdateAsync();
let isAvailable = response?.isAvailable;
if (isAvailable) {
let manifest = response.manifest;
Sentry.captureMessage(
`AboutAppView: Updates.manifest: ${JSON.stringify(manifest)}`,
);
setUpdateAvail(UPDATE_NEWER_AVAILABLE);
setUpdatedManifest(manifest);
} else {
setUpdateAvail(UPDATE_HAVE_LATEST);
}
} catch (ex) {
Sentry.captureException(ex);
console.error(`check for updates: ${ex.message}`);
}
};
const NameValue = ({
name,
value,
mono = false,
narrowWrapper = false,
color = 'black',
}) => {
if (typeof value !== 'string') {
value = JSON.stringify(value);
}
return (
<View style={styles.textRow}>
<View
style={narrowWrapper ? styles.narrowWrapper : styles.titleWrapper}>
<Text style={styles.titleText}>{name}</Text>
</View>
<View style={styles.valueWrapper}>
<Text
style={
mono ? {...styles.mono, color} : {...styles.valueText, color}
}>
{value}
</Text>
</View>
</View>
);
};
return (
<View>
<AccordionList
title={t('LABEL_ABOUT_APP', {APP_NAME: Constants.manifest.name})}
left={(props) => (
<List.Icon
style={styles.leftIcon}
{...props}
icon={MiscConstants.ICON_RN_ABOUT_APP}
/>
)}
renderWhenClosed={false}>
<NameValue
name="app name"
value={Constants.manifest?.name}
mono={true}
/>
<NameValue
name="full name"
value={Constants.manifest?.slug}
mono={true}
/>
<NameValue
name="platform"
value={Constants.manifest?.version}
mono={true}
/>
<NameValue name="channel" value={Updates?.releaseChannel} mono={true} />
<NameValue
name="release ID"
value={Constants.manifest?.releaseId}
mono={true}
/>
<NameValue
name="revision ID"
value={Constants.manifest?.revisionId}
mono={true}
/>
<NameValue
name="published"
value={Constants.manifest?.publishedTime}
mono={true}
/>
<NameValue
name="visibility"
value={Constants.manifest?.privacy}
mono={true}
/>
<View style={{borderWidth: 1, borderColor: '#CCC'}}>
<AccordionList
title={t('LABEL_MANIFEST_DUMP')}
left={(props) => (
<List.Icon
style={styles.leftIcon}
{...props}
icon={MiscConstants.ICON_RN_ABOUT_APP}
/>
)}
renderWhenClosed={false}>
<View>
<Button
style={
updateAvail === UPDATE_NEWER_AVAILABLE
? styles.buttonUpdate
: updateAvail === UPDATE_HAVE_LATEST
? styles.buttonNoUpdate
: styles.buttonNotChecked
}
onPress={checkForUpdate}>
{t('LABEL_CHECK_FOR_UPDATES')}
</Button>
{updateAvail === UPDATE_NEWER_AVAILABLE ? (
<View>
<Text style={{fontWeight: 'bold', color: 'green'}}>
{t('LABEL_NEW_UPDATE_AVAILABLE')}
</Text>
{Object.keys(updatedManifest).map((k, idx) => (
<NameValue
key={idx}
name={k}
value={updatedManifest[k]}
mono={true}
color={'purple'}
narrowWrapper={true}
/>
))}
</View>
) : updateAvail === UPDATE_HAVE_LATEST ? (
<Text style={{fontStyle: 'italic'}}>
{t('LABEL_YOU_HAVE_THE_LATEST')}
</Text>
) : (
<View />
)}
<View style={styles.textRow}>
<View style={styles.warningLabel}>
<Text style={styles.textSupportInfo}>
{t('LABEL_INFO_FOR_SUPPORT_TEAM').toLocaleUpperCase()}
</Text>
</View>
</View>
{Object.keys(Updates?.manifest).map((k, idx) => (
<NameValue
key={idx}
name={k}
value={Updates.manifest[k]}
mono={true}
color={'purple'}
narrowWrapper={true}
/>
))}
</View>
</AccordionList>
</View>
</AccordionList>
</View>
);
};
export default AboutAppView;
const getStyles = () => {
let WARN_COLOR = 'green';
return StyleSheet.create({
warningLabel: {
marginTop: hPct('2%'),
paddingVertical: hPct('1.5%'),
borderWidth: 1,
borderColor: WARN_COLOR,
justifyContent: 'center',
width: wPct('90%'),
marginBottom: hPct('1%'),
},
textSupportInfo: {
color: WARN_COLOR,
textAlign: 'center',
},
leftIcon: {
minHeight: hPct('6%'), // if no icon is provided
minWidth: wPct('10%'),
},
textSection: {
flexDirection: 'column',
},
textRow: {
flexDirection: 'row',
minWidth: wPct('95%'),
},
narrowWrapper: {
width: wPct('12%'),
marginRight: wPct('1%'),
},
titleWrapper: {
width: wPct('20%'),
marginRight: wPct('1%'),
borderBottomWidth: 1,
borderColor: '#EEE',
},
titleText: {
textAlign: 'right',
fontSize: 12,
},
valueWrapper: {
width: wPct('75%'),
borderBottomWidth: 1,
borderColor: '#EEE',
},
valueText: {
textAlign: 'left',
fontWeight: 'bold',
fontSize: 12,
},
mono: {
fontFamily: Platform.OS === 'ios' ? 'Menlo-Regular' : 'monospace',
fontSize: 16,
},
buttonNoUpdate: {
backgroundColor: 'red',
color: 'white',
},
buttonUpdate: {
backgroundColor: 'green',
color: 'white',
},
buttonNotChecked: {
backgroundColor: '#fff',
},
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment