1import React from 'react'; 2import { ScrollView, StyleSheet, TextInput, View } from 'react-native'; 3import { Linking } from 'expo'; 4 5import Button from '../components/Button'; 6import MonoText from '../components/MonoText'; 7import Colors from '../constants/Colors'; 8 9class TextInputButton extends React.Component< 10 { text: string }, 11 { text: string; parsed: string; canOpen: boolean } 12> { 13 constructor(props: { text: string }) { 14 super(props); 15 16 this.state = { 17 text: props.text, 18 parsed: '', 19 canOpen: false, 20 }; 21 } 22 23 componentDidMount() { 24 this.onChangeText(this.props.text); 25 } 26 27 onChangeText = async (text: string) => { 28 let parsedTextResult = ''; 29 const canOpenURL = await Linking.canOpenURL(text); 30 if (canOpenURL) { 31 const parsedText = await Linking.parse(text); 32 parsedTextResult = JSON.stringify(parsedText, null, 2); 33 } 34 35 this.setState({ text, parsed: parsedTextResult, canOpen: canOpenURL }); 36 } 37 38 handleClick = async () => { 39 const { text } = this.state; 40 try { 41 const supported = await Linking.canOpenURL(text); 42 43 if (supported) { 44 Linking.openURL(text); 45 } else { 46 const message = `Don't know how to open URI: ${text}`; 47 console.log(message); 48 alert(message); 49 } 50 } catch ({ message }) { 51 console.error(message); 52 } 53 } 54 55 render() { 56 const { text, parsed, canOpen } = this.state; 57 58 const buttonTitle = canOpen ? 'Open ' : 'Cannot Open '; 59 return ( 60 <View> 61 <View style={styles.textInputContainer}> 62 <TextInput 63 style={styles.textInput} 64 onChangeText={this.onChangeText} 65 value={text} 66 /> 67 <Button 68 title={buttonTitle} 69 onPress={this.handleClick} 70 disabled={!canOpen} 71 /> 72 </View> 73 <MonoText containerStyle={styles.itemText}>{parsed}</MonoText> 74 </View> 75 ); 76 } 77} 78 79interface State { 80 initialUrl?: string; 81} 82 83export default class LinkingScreen extends React.Component<{}, State> { 84 static navigationOptions = { 85 title: 'Linking', 86 }; 87 88 readonly state: State = {}; 89 90 componentDidMount() { 91 this.setupAsync(); 92 Linking.addEventListener('url', this.onEvent); 93 } 94 95 componentWillUnmount() { 96 Linking.removeEventListener('url', this.onEvent); 97 } 98 99 onEvent = ({ url }: any) => { 100 alert(`Linking url event: ${url}`); 101 } 102 103 setupAsync = async () => { 104 const initialUrl = await Linking.getInitialURL(); 105 this.setState({ initialUrl }); 106 } 107 108 render() { 109 return ( 110 <ScrollView style={styles.container}> 111 {this.state.initialUrl && ( 112 <TextInputButton text={this.state.initialUrl} /> 113 )} 114 <TextInputButton text="https://github.com/search?q=Expo" /> 115 <TextInputButton text="https://www.expo.io" /> 116 <TextInputButton text="http://www.expo.io" /> 117 <TextInputButton text="http://expo.io" /> 118 <TextInputButton text="fb://notifications" /> 119 <TextInputButton text="geo:37.484847,-122.148386" /> 120 <TextInputButton text="tel:9876543210" /> 121 </ScrollView> 122 ); 123 } 124} 125 126const styles = StyleSheet.create({ 127 container: { 128 paddingVertical: 16, 129 paddingHorizontal: 24, 130 flex: 1, 131 backgroundColor: Colors.greyBackground, 132 }, 133 textInputContainer: { 134 flexDirection: 'row', 135 maxWidth: '100%', 136 flexWrap: 'wrap', 137 justifyContent: 'space-between', 138 }, 139 textInput: { 140 height: 40, 141 flex: 1, 142 borderColor: Colors.border, 143 borderWidth: StyleSheet.hairlineWidth, 144 paddingHorizontal: 16, 145 marginRight: 16, 146 }, 147 itemText: { 148 borderWidth: 0, 149 flex: 1, 150 marginTop: 8, 151 marginBottom: 16, 152 paddingVertical: 18, 153 paddingLeft: 12, 154 }, 155}); 156