• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

akvo / nmis-mobile / 5385783612

27 Jun 2023 04:31AM UTC coverage: 69.565% (-16.2%) from 85.789%
5385783612

Pull #19

github

web-flow
Merge 7f4a3ae4c into 13b679e8c
Pull Request #19: Feature/13 initial formik implementation

146 of 231 branches covered (63.2%)

Branch coverage included in aggregate %.

265 of 265 new or added lines in 18 files covered. (100.0%)

286 of 390 relevant lines covered (73.33%)

10.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

32.26
/app/src/form/fields/TypeImage.js
1
import React from 'react';
2
import { View, PermissionsAndroid, StyleSheet, ActivityIndicator } from 'react-native';
3
import { Image, Button, Dialog } from '@rneui/themed';
4
import * as ImagePicker from 'expo-image-picker';
5
import { Stack } from '../../components';
6
import { FieldLabel } from '../support';
7
import { styles as formStyle } from '../styles';
8

9
// TODO: getImageBase64 (ARF)
10
// TODO: convertImageToBase64 (ARF)
11

12
const TypeImage = ({ onChange, keyform, id, name }) => {
15✔
13
  const [showDialog, setShowDialog] = React.useState(false);
3✔
14
  const [selectedImage, setSelectedImage] = React.useState(null);
3✔
15

16
  React.useEffect(() => {
3✔
17
    if (onChange) {
3!
18
      onChange(id, selectedImage);
×
19
    }
20
  }, [selectedImage, onChange]);
21

22
  const checkPermissions = async () => {
3✔
23
    try {
2✔
24
      const result = await PermissionsAndroid.check(
2✔
25
        PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
26
      );
27

28
      if (result) {
2!
29
        // Access granted
30
        return true;
2✔
31
      }
32

33
      // Ask for Access
34
      const granted = await PermissionsAndroid.request(
×
35
        PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
36
        {
37
          title: 'You need to give storage permission to download and save the file',
38
          message: 'App needs access to your camera ',
39
          buttonNeutral: 'Ask Me Later',
40
          buttonNegative: 'Cancel',
41
          buttonPositive: 'OK',
42
        },
43
      );
44

45
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
×
46
        console.info('You can use the camera');
×
47
        return true;
×
48
      }
49

50
      console.info('Camera permission denied');
×
51
      return false;
×
52
    } catch (err) {
53
      console.error(err);
×
54
      return false;
×
55
    }
56
  };
57

58
  async function handleShowDialog() {
59
    const result = await checkPermissions();
2✔
60
    if (result) {
2!
61
      setShowDialog(true);
2✔
62
      return true;
2✔
63
    }
64
    console.info('Access not granted!');
×
65
  }
66

67
  async function selectFile() {
68
    setShowDialog(false);
×
69
    try {
×
70
      const result = await ImagePicker.launchImageLibraryAsync({
×
71
        quality: 1,
72
      });
73
      if (result?.canceled) {
×
74
        console.info('You did not select any image.');
×
75
        return false;
×
76
      }
77
      setSelectedImage(result.assets[0]);
×
78
    } catch (err) {
79
      setSelectedImage(null);
×
80
      console.error(err);
×
81
      return false;
×
82
    }
83
  }
84

85
  async function handleCamera() {
86
    setShowDialog(false);
×
87
    try {
×
88
      const result = await ImagePicker.launchCameraAsync({
×
89
        quality: 1,
90
      });
91
      if (result?.canceled) {
×
92
        console.info('You did not select any image.');
×
93
        return false;
×
94
      }
95
      setSelectedImage(result.assets[0]);
×
96
    } catch (err) {
97
      setSelectedImage(null);
×
98
      console.error(err);
×
99
      return false;
×
100
    }
101
  }
102

103
  return (
3✔
104
    <View>
105
      <FieldLabel keyform={keyform} name={name} />
106
      <View style={styles.fieldImageContainer}>
107
        {selectedImage != null ? (
3!
108
          <Image
109
            source={{ uri: selectedImage?.uri }}
110
            containerStyle={styles.imagePreview}
111
            PlaceholderContent={<ActivityIndicator />}
112
            testID="image-preview"
113
          />
114
        ) : null}
115
        <Stack row columns={2}>
116
          <Button title="Select File" onPress={handleShowDialog} testID="btn-select-file" />
117
          <Button
118
            containerStyle={styles.buttonRemoveFile}
119
            title="Remove"
120
            color="secondary"
121
            onPress={() => setSelectedImage(null)}
×
122
            disabled={!selectedImage}
123
            testID="btn-remove"
124
          />
125
        </Stack>
126
        <Dialog
127
          isVisible={showDialog}
128
          onBackdropPress={() => setShowDialog(false)}
×
129
          testID="popup-dialog"
130
        >
131
          <Button
132
            title="Use Camera"
133
            type="outline"
134
            onPress={handleCamera}
135
            testID="btn-use-camera"
136
          />
137
          <Button
138
            containerStyle={styles.buttonFromGallery}
139
            title="From Gallery"
140
            type="outline"
141
            onPress={selectFile}
142
            testID="btn-from-gallery"
143
          />
144
        </Dialog>
145
      </View>
146
    </View>
147
  );
148
};
149

150
export default TypeImage;
151

152
const styles = StyleSheet.create({
15✔
153
  fieldImageContainer: {
154
    flex: 1,
155
    justifyContent: 'center',
156
    padding: 10,
157
  },
158
  imagePreview: { aspectRatio: 1, width: '100%', flex: 1, marginBottom: 15 },
159
  buttonRemoveFile: {
160
    marginLeft: 12,
161
  },
162
  buttonFromGallery: {
163
    marginTop: 12,
164
  },
165
});
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc