All files / atlas-mobile-ts/src/components PhotoPicker.tsx

0% Statements 0/54
0% Branches 0/16
0% Functions 0/11
0% Lines 0/53

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126                                                                                                                                                                                                                                                           
/* Copyright (C) Click & Push Accessibility, Inc - All Rights Reserved
 * Unauthorized copying of this file, via any medium is strictly prohibited
 * Proprietary and confidential
 * Written and maintained by the Click & Push Development team 
 * <dev@clicknpush.ca>, January 2022
 */
 
import * as ImagePicker from "expo-image-picker"
import { ImageInfo } from "expo-image-picker/build/ImagePicker.types"
import React, { useEffect, useState } from "react"
import {Alert, AlertButton, Linking, Platform, Text} from 'react-native'
import { Menu, MenuOption, MenuOptions, MenuTrigger, renderers } from "react-native-popup-menu"
import { colors, getMediaPermissions } from "../utils/GlobalUtils"
const {SlideInMenu} = renderers
 
export const PhotoPicker: React.FC<{photoSourceMenuOpened: boolean, cancel: () => void, onBeforeLaunchPicker?: () => void, onReceivedPhotoResult?: (result: ImageInfo) => void, menuType: 'slideup' | 'alert', multiple: boolean}> = ({photoSourceMenuOpened, cancel, onBeforeLaunchPicker, onReceivedPhotoResult, menuType, multiple}) => {
 
    useEffect(() => {
        Iif (photoSourceMenuOpened && menuType ==  'alert') {
            console.log("[PhotoPicker]: PhotoPicker is launching with menutype = " + menuType + " and multiple = " + multiple)
            showAlert()
        }
    }, [photoSourceMenuOpened])
 
    const showAlert = () => {
        if (Platform.OS == 'android') {
            Alert.alert(
                "Pick photo source", 
                "Where would like to get the photo from?",
                [
                    {text: 'Cancel', onPress: cancel, style: 'cancel'},
                    {text: 'Camera', onPress: () => selectNewPhoto('camera')},
                    {text: 'Library', onPress: () => selectNewPhoto('library')},
                ],
                {onDismiss: cancel, cancelable: true})
        }
        else Iif (Platform.OS == 'ios') {
            Alert.alert(
                "Pick photo source", 
                "Where would like to get the photo from?",
                [
                    {text: 'Camera', onPress: () => selectNewPhoto('camera')},
                    {text: 'Library', onPress: () => selectNewPhoto('library')},
                    {text: 'Cancel', onPress: cancel, style: 'cancel'},
                ],
                {onDismiss: cancel, cancelable: true})
        }
 
    }
 
    const selectNewPhoto = async (imageSource: 'camera' | 'library') => {
        Iif (onBeforeLaunchPicker) {
            onBeforeLaunchPicker()
        }
        
        console.log("[Permissions]: Checking photo permissions...")
        const granted = await getMediaPermissions();
 
        if (granted) {
            console.log("[Permissions]: Photo permissions are granted")
            const imageOptions: ImagePicker.ImagePickerOptions = {
                mediaTypes: ImagePicker.MediaTypeOptions.Images,
                base64: true,
                allowsEditing: true,
                quality: .5,
                allowsMultipleSelection: multiple
            }
 
            let result: ImagePicker.ImagePickerResult = {cancelled: true}
 
            try {
                Iif (imageSource === 'camera') {
                    console.log("[PhotoPicker]: Camera was selected as photo source, launching camera...")
                    result = await ImagePicker.launchCameraAsync(imageOptions)
                }
        
                Iif (imageSource === 'library') {
                    console.log("[PhotoPicker]: Image Library was selected as photo source, launching library...")
                    result = await ImagePicker.launchImageLibraryAsync(imageOptions)
                }   
                if (!result.cancelled) {
                    console.log("[PhotoPicker]: User selected image")
                    onReceivedPhotoResult(result as ImageInfo)
                }
                else {
                    console.log("[PhotoPicker]: User canceled image selection")
                    cancel()
                }
            } catch (error) {
                console.log("[PhotoPicker]: An error occurred during image selection: " + error)
                Alert.alert("Something went wrong when loading the selected image. Please try another image.")
                cancel()
            }
        }
        else {
            const permissionsButtons: AlertButton[] = [{text: 'Cancel', style: "cancel", onPress: cancel}]
            Iif (Platform.OS == 'ios')
                permissionsButtons.push({text: 'Go to settings', onPress: () => {
                    Linking.openURL('app-settings:')
                    cancel()
                }})
            Alert.alert(
                "Permissions needed", 
                "You need to grant camera/storage permissions to upload an image.",
                permissionsButtons,
                {onDismiss: cancel, cancelable: true})
        }
    }
 
    return (
        <>
        {menuType == 'slideup' ?
        <Menu renderer={SlideInMenu} style={{zIndex: 10}} opened={photoSourceMenuOpened} onBackdropPress={cancel} >
            <MenuTrigger />
            <MenuOptions optionsContainerStyle={{backgroundColor: colors.red}}>
                <MenuOption onSelect={async () => await selectNewPhoto('camera')} style={{padding: 20, alignItems: 'center', borderBottomWidth: 1, borderColor: 'white', marginHorizontal: 10}} >
                    <Text style={{fontSize: 20, color: 'white'}}>Select from camera</Text>
                </MenuOption>
                <MenuOption onSelect={async () => await selectNewPhoto('library')} style={{padding: 20, alignItems: 'center'}} >
                    <Text style={{fontSize: 20, color: 'white'}}>Select from library</Text>
                </MenuOption>
            </MenuOptions>
        </Menu> : null}
        </>
    )
}