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