react-native#BackHandler TypeScript Examples
The following examples show how to use
react-native#BackHandler.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: BatteryModal.tsx From hamagen-react-native with MIT License | 6 votes |
BatteryModal: FunctionComponent<Props> = ({ navigation }) => {
const dispatch = useDispatch();
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', handleExit);
return () => {
BackHandler.removeEventListener('hardwareBackPress', handleExit);
};
});
const handleExit = async () => {
dispatch({ type: USER_DISABLED_BATTERY, payload: false });
await AsyncStorage.setItem(USER_AGREED_TO_BATTERY, 'false');
navigation.goBack();
return true;
};
return (
<View style={styles.container}>
<HeaderButton type="close" onPress={handleExit} />
<BatteryPermission
onEnd={() => {
navigation.goBack();
}}
/>
</View>
);
}
Example #2
Source File: QuestionaireForm.tsx From SQUID with MIT License | 6 votes |
FormBackHandler = ({ onBack }) => {
useEffect(() => {
const backHandler = BackHandler.addEventListener(
"hardwareBackPress",
() => {
onBack()
return true
}
)
return () => backHandler.remove();
}, [onBack])
return null
}
Example #3
Source File: Toolbar.tsx From mobile with Apache License 2.0 | 6 votes |
Toolbar = ({title, navText, onIconClicked, accessibilityTitleAutoFocus}: ToolbarProps) => {
useEffect(() => {
if (Platform.OS !== 'android') {
return;
}
const subscription = BackHandler.addEventListener('hardwareBackPress', () => {
onIconClicked();
return true;
});
return () => subscription.remove();
}, [onIconClicked]);
return (
<Box flexDirection="row" alignItems="center" justifyContent="space-between" minHeight={56}>
<Box style={styles.invisible}>
<Button disabled text={navText} variant="text" onPress={() => {}} />
</Box>
{title !== '' && (
<Box flex={1} justifyContent="center" minWidth={100}>
<Text
variant="bodySubTitle"
color="overlayBodyText"
textAlign="center"
accessibilityAutoFocus={accessibilityTitleAutoFocus}
>
{title}
</Text>
</Box>
)}
<Box>
<Button testID="toolbarCloseButton" text={navText} variant="close" onPress={onIconClicked} />
</Box>
</Box>
);
}
Example #4
Source File: useBackButton.tsx From nlw2-proffy with MIT License | 6 votes |
export default function useBackButton(
ref: React.RefObject<NavigationContainerRef>
) {
React.useEffect(() => {
const subscription = BackHandler.addEventListener(
'hardwareBackPress',
() => {
const navigation = ref.current;
if (navigation == null) {
return false;
}
if (navigation.canGoBack()) {
navigation.goBack();
return true;
}
return false;
}
);
return () => subscription.remove();
}, [ref]);
}
Example #5
Source File: DataUpload.tsx From ito-app with GNU General Public License v3.0 | 6 votes |
DataUpload: React.FC<{
navigation: DataUploadScreenNavigationProp;
}> = ({navigation}) => {
const {t} = useTranslation();
useFocusEffect(
useCallback(() => {
const onBackPress = (): boolean => {
navigation.navigate('Home');
return true;
};
BackHandler.addEventListener('hardwareBackPress', onBackPress);
return (): void =>
BackHandler.removeEventListener('hardwareBackPress', onBackPress);
}, [navigation]),
);
return (
<View style={global.container}>
<Header
navigationButton={{
title: 'home',
fn: (): void => navigation.navigate('Home'),
}}
showHelp={true}
/>
<Text style={styles.thanks}>{t('dataUpload.thanks')}</Text>
</View>
);
}
Example #6
Source File: Start.tsx From save-food with MIT License | 6 votes |
Start = ({ navigation }: Props) => {
const { useSubscribe } = useSettingsContext()
const settings = useSubscribe((s) => s.settings)
const translations = useSubscribe((s) => s.translations.Start)
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', () => true)
return () => {
BackHandler.removeEventListener('hardwareBackPress', () => true)
}
}, [])
const doneBtnHandle = async () => {
await AsyncStorage.removeItem('start')
navigation.replace('Home')
}
return (
<Onboarding
showSkip={false}
onDone={doneBtnHandle}
pages={getPages(translations, settings.lang)}
/>
)
}
Example #7
Source File: Toolbar.tsx From mobile with Apache License 2.0 | 5 votes |
Toolbar = ({title, navText, navIcon, navLabel, onIconClicked}: ToolbarProps) => {
useEffect(() => {
if (Platform.OS !== 'android') {
return;
}
const subscription = BackHandler.addEventListener('hardwareBackPress', () => {
onIconClicked();
return true;
});
return () => subscription.remove();
}, [onIconClicked]);
if (Platform.OS === 'android') {
return (
<Box flex={1} flexDirection="row" alignItems="center" justifyContent="flex-start" padding="none" maxHeight={56}>
{navIcon && <TouchableIcon iconName={navIcon} label={navLabel} onPress={onIconClicked} />}
<Box padding="m">
<Text variant="bodySubTitle" color="overlayBodyText" accessibilityRole="header">
{title}
</Text>
</Box>
</Box>
);
}
return (
<Box flexDirection="row" alignItems="center" minHeight={56}>
<Box>
<Button text={navText} variant="text" onPress={onIconClicked} />
</Box>
{title !== '' && (
<Box flex={1} justifyContent="center" minWidth={100}>
<Text variant="bodySubTitle" color="overlayBodyText" textAlign="center" accessibilityRole="header">
{title}
</Text>
</Box>
)}
<Box style={styles.invisible}>
<Button disabled text={navText} variant="text" onPress={() => {}} />
</Box>
</Box>
);
}
Example #8
Source File: AllSet.tsx From hamagen-react-native with MIT License | 5 votes |
AllSet = ({ navigation, strings: { allSet: { allGood } }, locale, notificationData, setOnboardingRoutes }: Props) => {
useEffect(() => {
setTimeout(() => {
onboardingDoneActions();
}, 3000);
}, []);
useFocusEffect(
React.useCallback(() => {
const onBackPress = () => {
return true;
};
BackHandler.addEventListener('hardwareBackPress', onBackPress);
return () => {
BackHandler.removeEventListener('hardwareBackPress', onBackPress);
};
}, [])
);
const onboardingDoneActions = async () => {
try {
await AsyncStorage.multiSet([
[IS_FIRST_TIME, 'true'],
[DID_CLUSTER_LOCATIONS, 'true'],
[SICK_DB_UPDATED, 'true'],
[MENU_DOT_LAST_SEEN, VERSION_BUILD]
]);
// TODO: figure out why replace crash android on first upload
setOnboardingRoutes(false);
await startForegroundTimer();
await startSampling(locale, notificationData);
await scheduleTask();
} catch (error) {
onError({ error });
}
};
return (
<View style={styles.container}>
<LottieView
style={styles.loader}
source={require('../../assets/lottie/loader no mask.json')}
resizeMode="cover"
autoPlay
loop
/>
<Text style={styles.text} black>{allGood}</Text>
</View>
);
}
Example #9
Source File: FullscreenImageZoom.tsx From vsinder with Apache License 2.0 | 5 votes |
FullscreenImageZoomProvider: React.FC = ({ children }) => {
const srcRef = useRef("");
const [src, setSrc] = useState("");
srcRef.current = src;
useEffect(() => {
const onBackPress = () => {
if (srcRef.current) {
setSrc("");
return true;
} else {
return false;
}
};
BackHandler.addEventListener("hardwareBackPress", onBackPress);
return () =>
BackHandler.removeEventListener("hardwareBackPress", onBackPress);
}, []);
return (
<FullscreenImageZoomContext.Provider value={setSrc}>
{src ? (
<SafeAreaView
style={{
position: "absolute",
top: 0,
zIndex: 50,
flex: 1,
backgroundColor: "#000",
}}
>
<MyButton onPress={() => setSrc("")}>close</MyButton>
<ImageZoom
cropWidth={width}
cropHeight={height}
imageWidth={codeImageWidth}
imageHeight={codeImageHeight}
>
<ScrollView>
<Image
style={{
borderRadius: 9,
height: codeImageHeight,
width: codeImageWidth,
}}
resizeMode="contain"
source={{ uri: src }}
/>
</ScrollView>
</ImageZoom>
</SafeAreaView>
) : null}
{children}
</FullscreenImageZoomContext.Provider>
);
}
Example #10
Source File: registration.tsx From iotc-cpm-sample with MIT License | 5 votes |
export function Registration() {
const {state, dispatch} = useContext(ConfigContext);
const [user] = useUser();
const [numeric, setNumeric] = useState(false);
const [qr, setQR] = useState(false);
const onVerify = async (data: string) => {
if (user == null) {
throw new Error('User not logged in');
}
const creds = DecryptCredentials(data, user.id);
// connect to IoTCentral before passing over
let iotc = new IoTCClient(
creds.deviceId,
creds.scopeId,
IOTC_CONNECT.DEVICE_KEY,
creds.deviceKey,
);
iotc.setModelId(creds.modelId);
iotc.setLogging(IOTC_LOGGING.ALL);
await iotc.connect();
dispatch({
type: 'CONNECT',
payload: iotc,
});
};
const onBack = () => {
setQR(false);
setNumeric(false);
return true;
};
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', onBack);
return () => {
BackHandler.removeEventListener('hardwareBackPress', onBack);
};
}, []);
if (!user || state.centralClient !== undefined) {
return null;
}
if (numeric) {
return <NumericCode onVerify={onVerify} onClose={onBack} />;
}
if (qr) {
return <QRCode onVerify={onVerify} onClose={onBack} />;
}
return (
<View style={{flex: 4, ...style.container}}>
<View style={{flex: 1, justifyContent: 'center'}}>
<Name style={style.title}>{title}</Name>
</View>
<View style={{flex: 1, justifyContent: 'center'}}>
<Name style={style.instructions}>{instructions}</Name>
</View>
<View style={{flex: 2}}>
<CPMButton
mode="outlined"
style={style.button}
onPress={() => setNumeric(true)}>
{code}
</CPMButton>
<CPMButton
mode="contained"
style={{marginBottom: 50, ...style.button}}
onPress={() => setQR(true)}>
{scan}{' '}
</CPMButton>
<SimulatedButton />
</View>
<Footer text={footerText} />
</View>
);
}
Example #11
Source File: useBackgroundOverlay.tsx From react-native-template with MIT License | 5 votes |
function useBackgroundOverlay(visible: boolean, onTouchStart: () => void) {
const isFirstRender = useRef(true)
const opacity = useMemo(
() =>
isFirstRender.current
? 0
: timing({
from: visible ? 0 : 0.2,
to: visible ? 0.2 : 0,
}),
[visible]
)
useEffect(() => {
isFirstRender.current = false
}, [])
useFocusEffect(
React.useCallback(() => {
const onBackPress = () => {
if (visible) {
onTouchStart()
return true
} else {
return false
}
}
BackHandler.addEventListener("hardwareBackPress", onBackPress)
return () =>
BackHandler.removeEventListener("hardwareBackPress", onBackPress)
}, [onTouchStart, visible])
)
return (
<>
{visible && <StatusBar backgroundColor="grey" animated />}
<Animated.View
pointerEvents={visible ? "auto" : "none"}
onTouchStart={() => {
Keyboard.dismiss()
onTouchStart()
}}
style={[
styles.overlay,
{
opacity,
},
]}
/>
</>
)
}
Example #12
Source File: ExposureInstructions.tsx From hamagen-react-native with MIT License | 4 votes |
ExposureInstructions = ({ navigation, route }: Props) => {
const dispatch = useDispatch();
const {
isRTL,
locale,
languages,
externalUrls,
strings: {
scanHome: {
atPlace,
betweenHours,
inDate,
fromHour,
deviceCloseTag,
locationCloseTag
},
exposureInstructions: {
title,
editBtn,
subTitle,
showLess,
showMore,
finishBtn,
reportSite,
updateTitle,
updateSubTitle,
goIntoIsolation,
reportIsolation,
allInstructions,
themInstructions,
}
},
} = useSelector<Store, LocaleReducer>(state => state.locale);
const exposures = useSelector<Store, Exposure[]>(state => state.exposures.pastExposures.filter((exposure: Exposure) => exposure.properties.wasThere));
const [shouldShowMore, setShowMore] = useState(false);
useEffect(() => {
SplashScreen.hide();
// if edit button need to be shown then Exposure Instructions don't need to persists
AsyncStorage.setItem(INIT_ROUTE_NAME, 'ExposureInstructions');
BackHandler.addEventListener('hardwareBackPress', () => true);
return () => {
BackHandler.removeEventListener('hardwareBackPress', () => true);
};
}, []);
const [furtherInstructions, reportForm] = useMemo(() => {
const relevantLocale: string = Object.keys(languages.short).includes(locale) ? locale : 'he';
return [
externalUrls.furtherInstructions[relevantLocale],
externalUrls.reportForm[relevantLocale]
];
}, [languages.short, locale]);
const ExposureList = useMemo(() => exposures.map((exposure: Exposure) => {
let ListText;
if (exposure.properties.BLETimestamp) {
const time = moment(exposure.properties.BLETimestamp).startOf('hour');
const exposureDate = time.format('DD.MM.YY');
const exposureStartHour = time.format('HH:mm');
const exposureEndHour = time.add(1, 'hour').format('HH:mm');
ListText = (<Text>{`${deviceCloseTag}: ${inDate} ${exposureDate} ${betweenHours} ${exposureStartHour}-${exposureEndHour}`}</Text>);
} else {
const { Place, fromTime } = exposure.properties;
const time = moment();
ListText = (<Text>{`${locationCloseTag}: ${atPlace}${Place} ${inDate} ${moment(fromTime).format('DD.MM.YY')} ${fromHour} ${moment(fromTime).format('HH:mm')}`}</Text>);
}
return (
<Text style={{ fontSize: IS_SMALL_SCREEN ? 14 : 16, lineHeight: 17, marginVertical: IS_SMALL_SCREEN ? 5 : 10, letterSpacing: 0.2, textAlign: isRTL ? 'right' : 'left' }} key={exposure.properties.OBJECTID}>
<Text bold>• </Text>
{ListText}
</Text>
);
}), [exposures, locale]);
const renderActionButton = (icon: number, text: string, buttonText: string, action: () => void) => (
<View style={[styles.actionButtonContainer, IS_SMALL_SCREEN ? styles.actionButtonContainerSmall : styles.actionButtonContainerBig, IS_SMALL_SCREEN && { flexDirection: isRTL ? 'row-reverse' : 'row' }]}>
<Icon source={icon} width={22} height={35} />
<Text style={styles.actionText}>{text}</Text>
<TouchableOpacity style={styles.button} onPress={action}>
<Text style={styles.buttonText} bold>{buttonText}</Text>
</TouchableOpacity>
</View>
);
const RenderHeader = useMemo(() => route.params?.update
? (
<>
<Icon source={require('../../assets/main/exposureRefresh.png')} width={86} customStyles={{ marginBottom: 15 }} />
<Text style={styles.title} bold>{updateTitle}</Text>
<Text style={{ marginBottom: 3 }}>{updateSubTitle}</Text>
</>
)
: (
<>
<Text style={styles.title} bold>{title}</Text>
<Text style={{ marginBottom: 3 }}>{subTitle}</Text>
{shouldShowMore ? ExposureList : ExposureList.slice(0, 4)}
{exposures.length > 4 && (
<TouchableOpacity
style={{
flexDirection: isRTL ? 'row' : 'row-reverse',
alignItems: 'center'
}}
onPress={() => {
LayoutAnimation.create(
300,
LayoutAnimation.Types.spring,
LayoutAnimation.Properties.scaleXY
);
setShowMore(!shouldShowMore);
}}
>
<Icon source={require('../../assets/main/showMore.png')} width={9} height={5} customStyles={{ marginHorizontal: 7, transform: [{ rotateZ: shouldShowMore ? '180deg' : '0deg' }] }} />
<Text style={{ color: MAIN_COLOR, fontSize: 13 }} bold>{shouldShowMore ? showLess : showMore}</Text>
</TouchableOpacity>
)}
</>
),
[route.params?.update, shouldShowMore]);
return (
<ScrollView
bounces={false}
contentContainerStyle={styles.subContainer}
showsVerticalScrollIndicator={false}
>
{route.params?.showEdit && (
<TouchableOpacity
hitSlop={HIT_SLOP}
style={{
alignContent: 'center',
alignItems: 'center',
position: 'absolute',
top: PADDING_TOP(IS_SMALL_SCREEN ? 10 : 28),
flexDirection: isRTL ? 'row' : 'row-reverse',
[!isRTL ? 'right' : 'left']: IS_SMALL_SCREEN ? 10 : 25,
}}
onPress={() => navigation.navigate('ExposureDetected')}
>
<Icon
width={IS_SMALL_SCREEN ? 20 : 24}
source={require('../../assets/main/back.png')}
customStyles={{
transform: [{ rotate: !isRTL ? '0deg' : '180deg' }]
}}
/>
<Text
bold
style={{
fontSize: IS_SMALL_SCREEN ? 13 : 15,
color: MAIN_COLOR,
marginHorizontal: IS_SMALL_SCREEN ? 5 : 8
}}
>
{editBtn}
</Text>
</TouchableOpacity>
)}
<View style={{ justifyContent: 'flex-start', alignItems: 'center' }}>
{RenderHeader}
</View>
<View style={{ justifyContent: 'space-between' }}>
<Text style={{ marginBottom: IS_SMALL_SCREEN ? 12 : 25 }} bold>{themInstructions}</Text>
<View style={!IS_SMALL_SCREEN && { width: SCREEN_WIDTH - (23 * 2), flexDirection: isRTL ? 'row-reverse' : 'row', flexWrap: 'wrap', justifyContent: 'space-between', }}>
{renderActionButton(require('../../assets/main/isolation.png'), goIntoIsolation, allInstructions, () => Linking.openURL(furtherInstructions))}
{renderActionButton(require('../../assets/main/report.png'), reportIsolation, reportSite, () => Linking.openURL(reportForm))}
</View>
<Text
bold
onPress={() => {
navigation.navigate('ScanHome');
dispatch(moveAllToPastExposures());
AsyncStorage.removeItem(INIT_ROUTE_NAME);
}}
style={{
color: MAIN_COLOR,
marginTop: IS_SMALL_SCREEN ? 22 : 32,
fontSize: IS_SMALL_SCREEN ? 14 : 16
}}
>
{finishBtn}
</Text>
</View>
</ScrollView>
);
}
Example #13
Source File: ExposuresDetected.tsx From hamagen-react-native with MIT License | 4 votes |
ExposuresDetected = ({ navigation }: ExposuresDetectedProps) => {
const dispatch = useDispatch();
const { isRTL, strings: { scanHome: { inDate, fromHour, wereYouThere, wasNotMe, wasMe, doneBtn, suspectedExposure, events, possibleExposure, atPlace, showOnMap, betweenHours, possibleExposureBLE, locationCloseTag, deviceCloseTag, wasMeBle, wasMeOnly } } } = useSelector<Store, LocaleReducer>(state => state.locale);
const { exposures } = useSelector<Store, ExposuresReducer>(state => state.exposures);
const [anim] = useState(new Animated.Value(SCREEN_HEIGHT * 0.08));
const isOneBle = useMemo(() => exposures.length === 1 && exposures[0].properties.BLETimestamp !== null, [exposures]);
const flatListRef = useRef(null);
useEffect(() => {
if (exposures.length === 0) {
navigation.navigate('ScanHome');
} else {
SplashScreen.hide();
AsyncStorage.setItem(INIT_ROUTE_NAME, 'ExposureDetected');
BackHandler.addEventListener('hardwareBackPress', () => true);
return () => {
BackHandler.removeEventListener('hardwareBackPress', () => true);
};
}
}, []);
const showButton = (duration: number = 300) => {
Animated.timing(anim, {
toValue: 0,
duration,
useNativeDriver: true,
delay: 300
}).start();
};
// show button when moving to another page
// use case for single exposure. the user moves on click but if he returns for edit
useFocusEffect(
useCallback(() => {
if (!isOneBle
&& exposures.every(exposure => exposure.properties.wasThere !== null)) {
showButton(0);
}
}, [])
);
const setSelected = (index: number, wasThere: boolean) => {
dispatch(setExposureSelected({ index, wasThere }));
if (exposures.length === 1) {
editDone();
} else {
// find index of first card user didn't checked(was or not) and go to there˝
const emptyIndex = exposures.findIndex(exposure => exposure.properties.wasThere === null || exposure.properties.wasThere === undefined);
if (emptyIndex === -1) {
showButton();
} else if (index + 1 < exposures.length) {
setTimeout(() => {
if (flatListRef?.current) {
flatListRef?.current?.scrollToIndex({
index: index + 1,
viewOffset: 10
});
}
}, 300);
} else {
// all selected show finish button and findIndex get me last index
if (emptyIndex === -1 || exposures.length - 1 === emptyIndex) {
showButton();
} else {
flatListRef?.current?.scrollToIndex({
index: emptyIndex,
viewOffset: 10
});
}
}
}
};
const editDone = () => {
dispatch(dismissExposures());
// check if at least one exposure was checked a been there
const isExposed = exposures.some((exposure: Exposure) => exposure.properties.wasThere);
if (isExposed) {
// move to ExposureInstructions
const showEdit = exposures.some((exposure: Exposure) => !exposure.properties.BLETimestamp);
navigation.navigate('ExposureInstructions', { showEdit });
} else {
// move to ExposureRelief
navigation.navigate('ExposureRelief');
AsyncStorage.removeItem(INIT_ROUTE_NAME);
}
};
const RenderBleExposure = ({ index, exposure: { properties: { BLETimestamp, OBJECTID, Place } } }) => {
const [exposureDate, exposureStartHour, exposureEndHour] = useMemo(() => {
const time = moment(BLETimestamp).startOf('hour');
return [
time.format('DD.MM.YY'),
time.format('HH:mm'),
time.add(1, 'hour').format('HH:mm')
];
}, [BLETimestamp]);
let LocationText = null;
if (OBJECTID) {
LocationText = (
<>
<Text style={styles.exposureCardPlace} bold>
{`${atPlace}${Place}`}
</Text>
<View style={styles.exposureCardMapContainer}>
<Text style={styles.exposureCardMapText} onPress={() => dispatch(showMapModal(exposures[index]))}>{showOnMap}</Text>
</View>
</>
);
}
return (
<Animated.View style={[styles.detailsContainer]}>
<View style={{ flex: 1, alignItems: 'center' }}>
<Text style={styles.exposureLength}>{`${index + 1}/${exposures.length}`}</Text>
<Text style={styles.exposureCardTitle}>{possibleExposureBLE}</Text>
<Text style={{ fontSize: 17 }} bold>{`${inDate} ${exposureDate}${OBJECTID ? ' ' : '\n'}${betweenHours} ${exposureStartHour}-${exposureEndHour}`}</Text>
{LocationText}
</View>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<TouchableOpacity
style={[styles.bleActionBtn]}
onPress={() => setSelected(index, true)}
>
<Text style={[styles.actionBtnText, styles.actionBtnSelectedText]} bold>{exposures.length === 1 ? wasMeOnly : wasMeBle}</Text>
</TouchableOpacity>
</View>
<CardIdentifyTag isRTL={isRTL} text={deviceCloseTag} color="rgba(44,191,220,0.5)" />
</Animated.View>
);
};
const RenderGeoExposure = ({ index, exposure: { properties: { Place, fromTime, OBJECTID, wasThere } } }: RenderExposureProps) => {
const [wasThereSelected, wasNotThereSelected] = useMemo(() => {
if (wasThere === null) { return [false, false]; }
return [wasThere, !wasThere];
}, [wasThere]);
const [exposureDate, exposureHour] = useMemo(() => {
const time = moment(fromTime);
return [time.format('DD.MM.YY'), time.format('HH:mm')];
}, [fromTime]);
return (
<Animated.View style={[styles.detailsContainer]}>
<View style={{ alignItems: 'center' }}>
<Text style={styles.exposureLength}>{`${index + 1}/${exposures.length}`}</Text>
<Text style={styles.exposureCardTitle}>{possibleExposure}</Text>
<Text style={styles.exposureCardPlace} bold>
{`${atPlace}${Place} ${inDate} ${exposureDate} ${fromHour} ${exposureHour}`}
</Text>
<View style={styles.exposureCardMapContainer}>
<Text style={styles.exposureCardMapText} onPress={() => dispatch(showMapModal(exposures[index]))}>{showOnMap}</Text>
</View>
</View>
<View>
<Text style={styles.actionBtnTitle}>{wereYouThere}</Text>
<View style={styles.actionBtnContainer}>
<TouchableOpacity
style={[styles.actionBtnTouch, wasThereSelected && styles.actionBtnSelected]}
onPress={() => setSelected(index, true)}
>
<Text style={[styles.actionBtnText, wasThereSelected && styles.actionBtnSelectedText]} bold={wasThereSelected}>{wasMe}</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.actionBtnTouch, wasNotThereSelected && styles.actionBtnSelected]}
onPress={() => setSelected(index, false)}
>
<Text style={[styles.actionBtnText, wasNotThereSelected && styles.actionBtnSelectedText]} bold={wasNotThereSelected}>{wasNotMe}</Text>
</TouchableOpacity>
</View>
</View>
<CardIdentifyTag isRTL={isRTL} text={locationCloseTag} color="rgba(217,228,140,0.6)" />
</Animated.View>
);
};
return (
<>
<ScrollView
contentContainerStyle={styles.container}
bounces={false}
showsVerticalScrollIndicator={false}
>
<View style={{ alignItems: 'center', marginBottom: IS_SMALL_SCREEN ? 10 : 42 }}>
<Icon source={require('../../assets/main/exposures.png')} width={IS_SMALL_SCREEN ? 66 : 99} height={IS_SMALL_SCREEN ? 40 : 59} customStyles={{ marginBottom: 33 }} />
<Text style={styles.title} bold>{`${suspectedExposure} ${exposures.length} ${events}`}</Text>
</View>
<FlatList
horizontal
bounces={false}
ref={flatListRef}
data={exposures}
nestedScrollEnabled
keyExtractor={(item: Exposure) => {
if (item?.properties?.BLETimestamp) { return item.properties.BLETimestamp.toString(); }
return item.properties.OBJECTID.toString();
}}
renderItem={({ item, index }) => (item.properties?.BLETimestamp ? <RenderBleExposure exposure={item} index={index} /> : <RenderGeoExposure exposure={item} index={index} />)}
showsHorizontalScrollIndicator={false}
contentContainerStyle={{ paddingLeft: 14, paddingRight: 5 }}
/>
</ScrollView>
<Animated.View style={{ transform: [{ translateY: anim }] }}>
<TouchableOpacity
onPress={editDone}
style={{
width: SCREEN_WIDTH,
height: SCREEN_HEIGHT * 0.08,
backgroundColor: MAIN_COLOR,
justifyContent: 'center',
flexDirection: isRTL ? 'row-reverse' : 'row',
alignItems: 'center',
paddingBottom: PADDING_BOTTOM()
}}
>
<Icon
source={require('../../assets/main/imDoneUpdate.png')}
width={IS_SMALL_SCREEN ? 12 : 14}
height={IS_SMALL_SCREEN ? 10 : 12}
/>
<Text style={{ fontSize: IS_SMALL_SCREEN ? 15 : 18, color: 'white', marginHorizontal: 6 }} bold>{doneBtn}</Text>
</TouchableOpacity>
</Animated.View>
</>
);
}
Example #14
Source File: ScanHome.tsx From hamagen-react-native with MIT License | 4 votes |
ScanHome: FunctionComponent<ScanHomeProps> = (
{
navigation,
route,
isRTL,
strings,
locale,
languages,
externalUrls,
exposures,
pastExposures,
firstPoint,
enableBle,
batteryDisabled,
hideLocationHistory,
checkForceUpdate,
checkIfHideLocationHistory,
checkIfBleEnabled,
checkIfBatteryDisabled
}
) => {
const appStateStatus = useRef<AppStateStatus>('active');
const [{ hasLocation, hasNetwork, hasGPS }, setIsConnected] = useState({ hasLocation: true, hasNetwork: true, hasGPS: true });
useEffect(() => {
init();
}, []);
const init = async () => {
checkIfHideLocationHistory();
checkIfBatteryDisabled();
checkConnectionStatusOnLoad();
checkIfBleEnabled();
SplashScreen.hide();
if (exposures.length > 0) {
navigation.navigate('ExposureDetected');
} else {
checkForceUpdate();
await goToFilterDrivingIfNeeded(navigation);
const url = await Linking.getInitialURL();
if (url) {
return onOpenedFromDeepLink(url, navigation);
}
await syncLocationsDBOnLocationEvent();
}
};
useEffect(() => {
AppState.addEventListener('change', onAppStateChange);
NetInfo.addEventListener((state: NetInfoState) => setIsConnected({ hasLocation, hasNetwork: state.isConnected, hasGPS }));
DeviceEventEmitter.addListener(RNSettings.GPS_PROVIDER_EVENT, handleGPSProviderEvent);
return () => {
AppState.removeEventListener('change', onAppStateChange);
DeviceEventEmitter.removeListener(RNSettings.GPS_PROVIDER_EVENT, handleGPSProviderEvent);
};
}, [hasLocation, hasNetwork, hasGPS]);
useFocusEffect(
React.useCallback(() => {
const onBackPress = () => {
BackHandler.exitApp();
return true;
};
BackHandler.addEventListener('hardwareBackPress', onBackPress);
return () => {
BackHandler.removeEventListener('hardwareBackPress', onBackPress);
};
}, [])
);
const checkConnectionStatusOnLoad = async () => {
const locationPermission = await checkLocationPermissions();
const networkStatus = await NetInfo.fetch();
const GPSStatus = await RNSettings.getSetting(RNSettings.LOCATION_SETTING);
setIsConnected({ hasLocation: locationPermission === RESULTS.GRANTED, hasNetwork: networkStatus.isConnected, hasGPS: GPSStatus === RNSettings.ENABLED });
};
const onAppStateChange = async (state: AppStateStatus) => {
if (state === 'active' && appStateStatus.current !== 'active') {
checkIfHideLocationHistory();
checkConnectionStatusOnLoad();
checkIfBatteryDisabled();
}
appStateStatus.current = state;
};
const handleGPSProviderEvent = (e: any) => {
setIsConnected({ hasLocation, hasNetwork, hasGPS: e[RNSettings.LOCATION_SETTING] === RNSettings.ENABLED });
};
const exposureState = () => {
// user never got any exposure detected
if (exposures.length + pastExposures.length === 0) {
return 'pristine';
}
// check if user past exposures are relevant
// ie: is less then 14 days old
if (exposures.some(isAfter14Days) || pastExposures.some(isAfter14Days)) {
return 'relevant';
}
return 'notRelevant';
};
const RelevantState = () => {
if (!hasGPS || !hasLocation) return (<NoGPS {...strings.scanHome.noGPS} />);
if (!hasNetwork) return (<NoNetwork {...strings.scanHome.noNetwork} />);
return (
<NoExposures
isRTL={isRTL}
strings={strings}
firstPoint={firstPoint}
exposureState={exposureState()}
hideLocationHistory={hideLocationHistory}
enableBle={enableBle}
batteryDisabled={batteryDisabled}
locale={locale}
languages={languages}
externalUrls={externalUrls}
goToLocationHistory={() => navigation.navigate('LocationHistory')}
goToBluetoothPermission={() => navigation.navigate('Bluetooth')}
goToBatteryPermission={() => navigation.navigate('Battery')}
showBleInfo={route.params?.showBleInfo}
/>
);
};
return (
<View style={styles.container}>
<ScanHomeHeader
enableBle={enableBle}
languages={languages}
isRTL={isRTL}
locale={locale}
externalUrls={externalUrls}
strings={strings}
openDrawer={navigation.openDrawer}
/>
{RelevantState()}
</View>
);
}
Example #15
Source File: NetworkLogger.tsx From react-native-network-logger with MIT License | 4 votes |
NetworkLogger: React.FC<Props> = ({ theme = 'light', sort = 'desc' }) => {
const [requests, setRequests] = useState(
sortRequests(logger.getRequests(), sort)
);
const [request, setRequest] = useState<NetworkRequestInfo>();
const [showDetails, _setShowDetails] = useState(false);
const [mounted, setMounted] = useState(false);
const setShowDetails = useCallback((shouldShow: boolean) => {
_setShowDetails(shouldShow);
if (shouldShow) {
setBackHandler(() => setShowDetails(false));
} else {
setBackHandler(undefined);
}
}, []);
useEffect(() => {
logger.setCallback((updatedRequests: NetworkRequestInfo[]) => {
setRequests(sortRequests(updatedRequests, sort));
});
logger.enableXHRInterception();
setMounted(true);
return () => {
// no-op if component is unmounted
logger.setCallback(() => {});
};
}, [sort]);
useEffect(() => {
const onBack = () => {
if (showDetails) {
setShowDetails(false);
return true;
}
// Let default back handler take over
return false;
};
const backHandler = BackHandler.addEventListener(
'hardwareBackPress',
onBack
);
return () => backHandler.remove();
}, [showDetails, setShowDetails]);
const showMore = () => {
Alert.alert('More Options', undefined, [
{
text: 'Clear Logs',
onPress: () => logger.clearRequests(),
style: 'destructive',
},
{ text: 'Cancel', style: 'cancel' },
]);
};
return (
<ThemeContext.Provider value={theme}>
<View style={styles.visible}>
{showDetails && !!request && (
<View style={styles.visible}>
<RequestDetails
onClose={() => setShowDetails(false)}
request={request}
/>
</View>
)}
<View style={showDetails && !!request ? styles.hidden : styles.visible}>
{mounted && !logger.enabled && !requests.length ? (
<Unmounted />
) : (
<RequestList
requests={requests}
onShowMore={showMore}
showDetails={showDetails && !!request}
onPressItem={(item) => {
setRequest(item);
setShowDetails(true);
}}
/>
)}
</View>
</View>
</ThemeContext.Provider>
);
}
Example #16
Source File: PartyScreen.tsx From lets-fork-native with MIT License | 4 votes |
PartyScreen = React.memo((props: Props) => {
const {
navigation, party, route, setParty, ws,
} = props
const [snapIndex, setSnapIndex] = React.useState(2)
const [finished, setFinished] = React.useState<boolean>(false)
const [restaurants, setRestaurants] = React.useState<Restaurant[]>()
const headerHeight = useHeaderHeight()
const viewHeight = env.ADS ? height - headerHeight - 50 : height - headerHeight
if (party?.error) {
Alert.alert(
'Yike! Something went wrong',
party.error,
[
{
text: 'OK',
onPress: (): void => {
navigation.navigate('Home')
setParty({} as Party)
},
},
],
{ cancelable: false },
)
}
// Request more cards with 3 remaining to prevent
// having to show loader
React.useEffect(() => {
if (restaurants && restaurants?.length === 3) {
ws.send(JSON.stringify({ type: 'request-more' }))
}
}, [restaurants, restaurants?.length, ws])
// Deep linking will open the app to the party screen
// but the party still needs to be joined
React.useEffect(() => {
if (route?.params?.id) {
ws.send(JSON.stringify({ type: 'join', payload: { party_id: route?.params?.id } }))
}
}, [route?.params?.id, ws])
// When anyone requests more cards, they are set in current
// and this useEffect loads the new cards into the restaurants array
const prevState = usePrevious(party || {} as Party)
React.useEffect(() => {
if (JSON.stringify(prevState.current) !== JSON.stringify(party?.current)) {
if (party?.current?.length && restaurants) {
const res = [...restaurants, ...party?.current]
setRestaurants(res)
}
}
}, [party, prevState, restaurants])
// Custom android back button
useFocusEffect( // eslint-disable-line
React.useCallback(() => {
const onBackPress = (): boolean => {
Alert.alert(
'Are you sure you want to exit?',
'Exiting will make you lose all data in this party',
[
{ text: 'Cancel' },
{
text: 'OK',
onPress: (): void => {
ws.send(JSON.stringify({ type: 'quit' }))
navigation.navigate('Home')
setParty({} as Party)
},
},
],
{ cancelable: true },
)
return true
}
BackHandler.addEventListener('hardwareBackPress', onBackPress)
return (): void => BackHandler.removeEventListener('hardwareBackPress', onBackPress)
}, [navigation, setParty, ws]),
)
const handleSwipeRight = (id: string): void => {
ws.send(JSON.stringify({ type: 'swipe-right', payload: { restaurant_id: id } }))
}
if (party?.status === 'waiting') {
return <Share party={party} ws={ws} />
}
if (finished || party?.total === 0) {
return (
<View
style={{
...styles.waiting,
height: viewHeight,
}}
>
<Text style={styles.text}>
No more restaurants.
Go through the list again or try expanding your search range.
</Text>
<Button
size="sm"
color="purple"
onPress={(): void => {
setFinished(false)
setRestaurants(party?.restaurants)
}}
>
START OVER
</Button>
</View>
)
}
if (!party || !party.restaurants) {
return (
<View
style={{
...styles.waiting,
height: viewHeight,
}}
>
<ActivityIndicator size="large" />
</View>
)
}
const current = restaurants?.length
? restaurants[0] : party.restaurants[0]
return (
<SafeAreaView style={styles.container}>
<View
// disable swiping while BottomSheet is open
pointerEvents={snapIndex !== 2 ? 'none' : 'auto'}
style={{ height: viewHeight, zIndex: 0 }}
>
<SwipeWindow
handleSwipeRight={handleSwipeRight}
restaurants={restaurants || party.restaurants}
setFinished={setFinished}
setRestaurants={setRestaurants}
/>
</View>
<ScrollBottomSheet
componentType="ScrollView"
contentContainerStyle={styles.scrollBottomSheet}
snapPoints={[100, 100, viewHeight - BOTTOM_BAR_HEIGHT]}
initialSnapIndex={2}
onSettle={setSnapIndex}
renderHandle={(): React.ReactElement => <Handle />}
animationConfig={{
duration: 100,
}}
>
<Details restaurant={current} />
</ScrollBottomSheet>
</SafeAreaView>
)
})