1import Constants, { AppOwnership } from 'expo-constants'; 2import * as Linking from 'expo-linking'; 3import React from 'react'; 4import { ScrollView, StyleSheet, TextInput, View } from 'react-native'; 5 6import Button from '../components/Button'; 7import MonoText from '../components/MonoText'; 8import Colors from '../constants/Colors'; 9 10async function canOpenURL(url: string): Promise<boolean> { 11 if ( 12 Constants.appOwnership === AppOwnership.Expo || 13 Constants.appOwnership === AppOwnership.Guest 14 ) { 15 return true; 16 } 17 return Linking.canOpenURL(url); 18} 19 20function TextInputButton({ text }: { text: string }) { 21 const [link, setLink] = React.useState<string>(text); 22 const [parsed, setParsed] = React.useState<string>(''); 23 const [canOpen, setCanOpen] = React.useState<boolean>(false); 24 25 React.useEffect(() => { 26 onChangeText(text); 27 }, [text]); 28 29 const onChangeText = async (text: string) => { 30 let parsedTextResult = ''; 31 const supported = await canOpenURL(text); 32 if (supported) { 33 const parsedText = await Linking.parse(text); 34 parsedTextResult = JSON.stringify(parsedText, null, 2); 35 } 36 37 setLink(text); 38 setParsed(parsedTextResult); 39 setCanOpen(supported); 40 }; 41 42 const handleClick = async () => { 43 try { 44 const supported = await canOpenURL(link); 45 46 if (supported) { 47 Linking.openURL(link); 48 } else { 49 const message = `Don't know how to open URI: ${link}`; 50 console.log(message); 51 alert(message); 52 } 53 } catch ({ message }) { 54 console.error(message); 55 } 56 }; 57 58 const buttonTitle = canOpen ? 'Open ' : 'Cannot Open '; 59 return ( 60 <View> 61 <View style={styles.textInputContainer}> 62 <TextInput style={styles.textInput} onChangeText={onChangeText} value={link} /> 63 <Button title={buttonTitle} onPress={handleClick} disabled={!canOpen} /> 64 </View> 65 <MonoText containerStyle={styles.itemText}>{parsed}</MonoText> 66 </View> 67 ); 68} 69 70export default function LinkingScreen() { 71 const url = Linking.useURL(); 72 73 React.useEffect(() => { 74 if (url) { 75 alert(`Linking url event: ${url}`); 76 } 77 }); 78 79 return ( 80 <ScrollView style={styles.container}> 81 <Button 82 title="Open Settings" 83 onPress={() => { 84 Linking.openSettings(); 85 }} 86 /> 87 {url && <TextInputButton text={Linking.createURL('deep-link')} />} 88 <TextInputButton text="https://github.com/search?q=Expo" /> 89 <TextInputButton text="https://www.expo.dev" /> 90 <TextInputButton text="http://www.expo.dev" /> 91 <TextInputButton text="http://expo.dev" /> 92 <TextInputButton text="fb://notifications" /> 93 <TextInputButton text="geo:37.484847,-122.148386" /> 94 <TextInputButton text="tel:9876543210" /> 95 </ScrollView> 96 ); 97} 98 99LinkingScreen.navigationOptions = { 100 title: 'Linking', 101}; 102 103const styles = StyleSheet.create({ 104 container: { 105 paddingVertical: 16, 106 paddingHorizontal: 24, 107 flex: 1, 108 backgroundColor: Colors.greyBackground, 109 }, 110 textInputContainer: { 111 flexDirection: 'row', 112 maxWidth: '100%', 113 flexWrap: 'wrap', 114 justifyContent: 'space-between', 115 }, 116 textInput: { 117 height: 40, 118 flex: 1, 119 borderColor: Colors.border, 120 borderWidth: StyleSheet.hairlineWidth, 121 paddingHorizontal: 16, 122 marginRight: 16, 123 }, 124 itemText: { 125 borderWidth: 0, 126 flex: 1, 127 marginTop: 8, 128 marginBottom: 16, 129 paddingVertical: 18, 130 paddingLeft: 12, 131 }, 132}); 133