1import * as SecureStore from 'expo-secure-store';
2import * as React from 'react';
3import { Alert, Platform, ScrollView, Text, TextInput, View } from 'react-native';
4
5import ListButton from '../components/ListButton';
6import { useResolvedValue } from '../utilities/useResolvedValue';
7
8export default function SecureStoreScreen() {
9  const [isAvailable, error] = useResolvedValue(SecureStore.isAvailableAsync);
10
11  const warning = React.useMemo(() => {
12    if (error) {
13      return `An unknown error occurred while checking the API availability: ${error.message}`;
14    } else if (isAvailable === null) {
15      return 'Checking availability...';
16    } else if (isAvailable === false) {
17      return 'SecureStore API is not available on this platform.';
18    }
19    return null;
20  }, [error, isAvailable]);
21
22  if (warning) {
23    return (
24      <View style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}>
25        <Text>{warning}</Text>
26      </View>
27    );
28  }
29
30  return <SecureStoreView />;
31}
32
33function SecureStoreView() {
34  const [key, setKey] = React.useState<string | undefined>();
35  const [value, setValue] = React.useState<string | undefined>();
36
37  const _setValue = async (value: string, key: string) => {
38    try {
39      console.log('SecureStore: ' + SecureStore);
40      await SecureStore.setItemAsync(key, value, {});
41      Alert.alert('Success!', 'Value: ' + value + ', stored successfully for key: ' + key, [
42        { text: 'OK', onPress: () => {} },
43      ]);
44    } catch (e) {
45      Alert.alert('Error!', e.message, [{ text: 'OK', onPress: () => {} }]);
46    }
47  };
48
49  const _getValue = async (key: string) => {
50    try {
51      const fetchedValue = await SecureStore.getItemAsync(key, {});
52      Alert.alert('Success!', 'Fetched value: ' + fetchedValue, [
53        { text: 'OK', onPress: () => {} },
54      ]);
55    } catch (e) {
56      Alert.alert('Error!', e.message, [{ text: 'OK', onPress: () => {} }]);
57    }
58  };
59
60  const _deleteValue = async (key: string) => {
61    try {
62      await SecureStore.deleteItemAsync(key, {});
63      Alert.alert('Success!', 'Value deleted', [{ text: 'OK', onPress: () => {} }]);
64    } catch (e) {
65      Alert.alert('Error!', e.message, [{ text: 'OK', onPress: () => {} }]);
66    }
67  };
68
69  return (
70    <ScrollView
71      style={{
72        flex: 1,
73        padding: 10,
74      }}>
75      <TextInput
76        style={{
77          marginBottom: 10,
78          padding: 10,
79          height: 40,
80          ...Platform.select({
81            ios: {
82              borderColor: '#ccc',
83              borderWidth: 1,
84              borderRadius: 3,
85            },
86          }),
87        }}
88        placeholder="Enter a value to store (ex. pw123!)"
89        value={value}
90        onChangeText={setValue}
91      />
92      <TextInput
93        style={{
94          marginBottom: 10,
95          padding: 10,
96          height: 40,
97          ...Platform.select({
98            ios: {
99              borderColor: '#ccc',
100              borderWidth: 1,
101              borderRadius: 3,
102            },
103          }),
104        }}
105        placeholder="Enter a key for the value (ex. password)"
106        value={key}
107        onChangeText={setKey}
108      />
109      {value && key && (
110        <ListButton onPress={() => _setValue(value, key)} title="Store value with key" />
111      )}
112      {key && <ListButton onPress={() => _getValue(key)} title="Get value with key" />}
113      {key && <ListButton onPress={() => _deleteValue(key)} title="Delete value with key" />}
114    </ScrollView>
115  );
116}
117
118SecureStoreScreen.navigationOptions = {
119  title: 'SecureStore',
120};
121