Skip to content

Instantly share code, notes, and snippets.

@wheelie33
Last active November 1, 2022 18:02
Show Gist options
  • Save wheelie33/676a194ce6ee05703187a7821a24e715 to your computer and use it in GitHub Desktop.
Save wheelie33/676a194ce6ee05703187a7821a24e715 to your computer and use it in GitHub Desktop.
Cropping Crash
Fatal: TypeError null is not an object (evaluating 'v.default.handleSetJSResponder')
"dependencies": {
"@expo/react-native-action-sheet": "^4.0.0",
"@expo/vector-icons": "^13.0.0",
"@react-native-async-storage/async-storage": "~1.17.3",
"@react-native-community/netinfo": "9.3.0",
"@react-navigation/bottom-tabs": "^6.4.0",
"@react-navigation/native": "^6.0.13",
"@react-navigation/stack": "^6.3.1",
"expo": "~46.0.13",
"expo-application": "~4.2.2",
"expo-av": "~12.0.4",
"expo-camera": "~12.3.0",
"expo-constants": "~13.2.4",
"expo-device": "~4.3.0",
"expo-image-cropper": "^1.0.9",
"expo-image-picker": "~13.3.1",
"expo-intent-launcher": "~10.3.0",
"expo-linking": "~3.2.2",
"expo-local-authentication": "~12.3.0",
"expo-localization": "~13.1.0",
"expo-notifications": "~0.16.1",
"expo-secure-store": "~11.3.0",
"expo-splash-screen": "~0.16.2",
"expo-status-bar": "~1.4.0",
"expo-system-ui": "~1.3.0",
"expo-updates": "~0.14.6",
"firebase": "9.4.1",
"jwt-decode": "^3.1.2",
"react": "18.0.0",
"react-native": "0.69.6",
"react-native-exception-handler": "^2.10.10",
"react-native-gifted-chat": "^1.0.4",
"react-native-safe-area-context": "4.3.1",
"react-native-screens": "~3.15.0",
"react-native-uuid": "^2.0.1"
},
import React, { useRef, useState } from "react"
import { View, Text, StyleSheet, TouchableOpacity, Image, Button, SafeAreaView } from "react-native"
import { Ionicons, MaterialCommunityIcons, Feather } from "@expo/vector-icons"
import * as ImagePicker from "expo-image-picker"
import ImageEditor from "expo-image-cropper"
import { Camera } from "expo-camera"
import useAuth from "../AuthContext/AuthContext"
import { useActionSheet } from "@expo/react-native-action-sheet"
function ProfileImagesScreen() {
let cameraRef = useRef()
const [uploadStatus, setUploadStatus] = useState(false)
const [isUploading, setIsUploading] = useState(false)
const [hasPermission, setHasPermission] = useState(null)
const [type, setType] = useState(Camera.Constants.Type.front)
const [useFlash, setUseFlash] = useState(Camera.Constants.FlashMode.on)
const [photo, setPhoto] = useState(null)
const [selectedPhoto, setSelectedPhoto] = useState(null)
const [showEditor, setShowEditor] = useState(false)
const [profilePhoto, setProfilePhoto] = useState("https://placekitten.com/100/100")
const [showCamera, setShowCamera] = useState(false)
const { authState } = useAuth()
const { showActionSheetWithOptions } = useActionSheet()
const userId = authState.profile.userId
const buttonClickedHandler = () => {
const options = ["Take Photo", "Choose from Library", "Cancel"]
const cancelButtonIndex = 2
showActionSheetWithOptions(
{
options,
cancelButtonIndex,
},
(selectedIndex) => {
switch (selectedIndex) {
case 0: {
// Take Photo
;(async () => {
const { status } = await Camera.requestCameraPermissionsAsync()
setHasPermission(status === "granted")
setShowCamera(true)
})()
break
}
case 1: {
// Choose from Library
alert("Choose from Library")
break
}
case cancelButtonIndex:
// Canceled
}
}
)
}
const takePhoto = async () => {
if (!cameraRef) return
const options = {
quality: 0.5,
base64: false,
exif: false,
skipProcessing: true,
}
console.log("Taking photo")
const newPhoto = await cameraRef.current.takePictureAsync(options)
setShowCamera(false)
setPhoto(newPhoto)
}
if (showCamera) {
if (hasPermission === null || hasPermission === false) {
alert("No access to camera")
setShowCamera(false)
setPhoto(null)
}
const iconSize = 36
return (
<Camera ref={cameraRef} style={styles.photoPreviewContainer} type={type} flashMode={useFlash}>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={() => setType(type === Camera.Constants.Type.back ? Camera.Constants.Type.front : Camera.Constants.Type.back)}>
<MaterialCommunityIcons name='rotate-360' size={iconSize} color={type === Camera.Constants.Type.back ? "white" : "yellow"} />
</TouchableOpacity>
<TouchableOpacity onPress={takePhoto}>
<Ionicons name='camera-sharp' size={iconSize} color='white' />
</TouchableOpacity>
<TouchableOpacity
onPress={() => setUseFlash(useFlash === Camera.Constants.FlashMode.off ? Camera.Constants.FlashMode.on : Camera.Constants.FlashMode.off)}
>
<Ionicons name='flash' size={iconSize} color={useFlash === Camera.Constants.FlashMode.off ? "white" : "yellow"} />
</TouchableOpacity>
<TouchableOpacity onPress={() => setShowCamera(false)}>
<Feather name='x' size={iconSize} color='white' />
</TouchableOpacity>
</View>
</Camera>
)
}
if (photo != null) {
return (
<SafeAreaView style={styles.photoPreviewContainer}>
<Image source={{ uri: photo.uri }} style={styles.previewImage} />
<View style={styles.buttonContainer}>
<Button
title='Use Photo'
onPress={async () => {
const fileName = Math.round(Date.now() / 1000)
//await uploadMedia(fileName, photo.uri)
setShowCamera(false)
setSelectedPhoto(photo.uri)
setPhoto(null)
setShowEditor(true)
}}
/>
<Button
title='Take another'
onPress={() => {
setPhoto(null)
setShowCamera(true)
}}
/>
<Button
title='Cancel'
onPress={() => {
setShowCamera(false)
setPhoto(null)
}}
/>
</View>
</SafeAreaView>
)
}
if (showEditor) {
return (
<ImageEditor
imageUri={selectedPhoto}
fixedAspectRatio={1 / 1}
lockAspectRatio={true}
minimumCropDimensions={{
width: 150,
height: 150,
}}
onEditingCancel={() => {
setShowCamera(false)
setPhoto(null)
setSelectedPhoto(null)
setShowEditor(false)
}}
onEditingComplete={(image) => {
const fileName = Math.round(Date.now() / 1000)
//await uploadMedia(fileName, photo.uri)
setShowCamera(false)
setSelectedPhoto(null)
setPhoto(null)
setShowEditor(false)
setProfilePhoto(image.uri)
}}
/>
)
}
return (
<View style={styles.screen}>
<View style={styles.profileImageContainer}>
<Image source={{ uri: profilePhoto }} style={styles.image} />
<View style={styles.cameraButtonContainer}>
<TouchableOpacity style={styles.button} onPress={buttonClickedHandler}>
<Ionicons name='camera-sharp' size={24} style={{ color: "#C0C0C0" }} />
</TouchableOpacity>
</View>
</View>
</View>
)
}
// Styles
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
profileImageContainer: {
width: 150,
height: 150,
},
image: {
width: 150,
height: 150,
position: "absolute",
top: 0,
left: 0,
},
cameraButtonContainer: {
padding: 5,
backgroundColor: "rgba(0,0,0,0.35)",
position: "absolute",
bottom: 0,
right: 4,
},
photoPreviewContainer: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
buttonContainer: {
flex: 1,
flexDirection: "row",
justifyContent: "space-between",
backgroundColor: "black",
position: "absolute",
bottom: 0,
left: 0,
right: 0,
padding: 12,
},
previewImage: {
alignSelf: "stretch",
flex: 1,
},
})
export default ProfileImagesScreen
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment