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