i want to select pdf from my device and then after clicking on crop buton i want to be able to crop on the pdf selected , i have already select pdf and display it , but when i click on confirm button to confirm the crop i got this error :
WARN Possible Unhandled Promise Rejection (id: 0): TypeError: undefined is not a function TypeError: undefined is not a function at ?anon_0_ (http://10.0.2.2:8081/component\PdfEditor.bundle?platform=android&app=com.awesomeproject&modulesOnly=true&dev=true&minify=false&runModule=true&shallow=true:60:50)
i am using @react-native-community/image-editor , react-native-view-shot , react-native-pdf, react-native-document-picker
import React, { useState, useRef } from 'react';
import { Button, View, StyleSheet, TouchableOpacity, Text, PanResponder } from 'react-native';
import DocumentPicker, { DocumentPickerResponse } from 'react-native-document-picker';
import Pdf from 'react-native-pdf';
import { captureRef } from 'react-native-view-shot';
import ImageEditor from '@react-native-community/image-editor';
const PdfEditor = () => {
const [pdfUri, setPdfUri] = useState<string | null>(null);
const [cropping, setCropping] = useState(false);
const [cropRect, setCropRect] = useState({ x: 0, y: 0, width: 0, height: 0 });
const pdfRef = useRef<Pdf>(null);
const pickPdf = async () => {
try {
const response: DocumentPickerResponse[] = await DocumentPicker.pick({
type: [DocumentPicker.types.pdf],
});
const fileUri = response[0].uri;
setPdfUri(fileUri);
} catch (err) {
console.log('Document picker error:', err);
}
};
const closePdf = () => {
setPdfUri(null);
};
const handleCrop = async () => {
if (pdfLoaded && pdfRef.current) {
const page = await pdfRef.current.getPage(1);
const pageWidth = page.width;
const pageHeight = page.height;
const cropWidth = cropRect.width * pageWidth;
const cropHeight = cropRect.height * pageHeight;
const cropX = cropRect.x * pageWidth;
const cropY = pageHeight - ((cropRect.y + cropRect.height) * pageHeight);
captureRef(pdfRef.current, {
format: 'png',
quality: 1,
result: 'data-uri',
}).then((uri) => {
ImageEditor.cropImage(
uri,
{
offset: { x: cropX, y: cropY },
size: { width: cropWidth, height: cropHeight },
},
(croppedUri) => {
setPdfUri(croppedUri);
setCropping(false);
},
);
}).catch((error) => {
console.log('Capture error:', error);
});
}
};
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: () => true,
onPanResponderGrant: (event, gestureState) => {
setCropRect({ x: gestureState.x0, y: gestureState.y0, width: 0, height: 0 });
},
onPanResponderMove: (event, gestureState) => {
const { x0, y0, moveX, moveY } = gestureState;
const x = Math.min(x0, moveX);
const y = Math.min(y0, moveY);
const width = Math.abs(moveX - x0);
const height = Math.abs(moveY - y0);
setCropRect({ x, y, width, height });
},
onPanResponderRelease: () => {
setCropping(false);
},
})
).current;
const [pdfLoaded, setPdfLoaded] = useState(false);
return (
<View style={styles.container}>
{pdfUri ? (
<>
<View style={styles.pdfContainer}>
<Pdf
ref={pdfRef}
source={{ uri: pdfUri }}
onLoadComplete={(numberOfPages) => {
console.log(`Number of pages: ${numberOfPages}`);
}}
onPageChanged={(page) => {
console.log(`Current page: ${page}`);
setPdfLoaded(true);
}}
onError={(error) => {
console.log('Error while displaying PDF:', error);
}}
style={styles.pdf}
/>
{cropping && (
<View style={[styles.cropRect, {
left: cropRect.x,
top: cropRect.y,
width: cropRect.width,
height: cropRect.height,
transform: [{ scaleY: -1 }]
}]} pointerEvents="none" />
)}
</View>
<View style={styles.buttonsContainer}>
<TouchableOpacity style={styles.cropButton} onPress={() => setCropping(true)}>
<Text style={styles.cropButtonText}>Crop</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.closeButton} onPress={closePdf}>
<Text style={styles.closeButtonText}>Close</Text>
</TouchableOpacity>
</View>
</>
) : (
<Button title="Pick PDF" onPress={pickPdf} />
)}
{cropping && (
<View style={styles.cropOverlay}>
<View style={styles.cropView}>
<View style={[styles.cropRect, {
left: cropRect.x,
top: cropRect.y,
width: cropRect.width,
height: cropRect.height,
transform: [{ scaleY: -1 }]
}]} {...panResponder.panHandlers} />
<TouchableOpacity style={styles.cropConfirmButton} onPress={handleCrop}>
<Text style={styles.cropButtonText}>Confirm</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.cropCancelButton} onPress={() => setCropping(false)}>
<Text style={styles.cropButtonText}>Cancel</Text>
</TouchableOpacity>
</View>
</View>
)}
</View>
);
};
and this is my package.json
{
"name": "AwesomeProject",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"lint": "eslint .",
"start": "react-native start",
"test": "jest"
},
"dependencies": {
"@react-native-community/image-editor": "^2.3.0",
"react": "18.2.0",
"react-native": "0.71.3",
"react-native-blob-util": "^0.17.2",
"react-native-canvas": "^0.1.38",
"react-native-document-picker": "^8.1.3",
"react-native-pdf": "^6.6.2",
"react-native-pdftron": "^3.0.2-beta.57",
"react-native-sqlite-storage": "^6.0.1",
"react-native-view-shot": "^3.5.0"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native-community/eslint-config": "^3.2.0",
"@tsconfig/react-native": "^2.0.2",
"@types/jest": "^29.2.1",
"@types/react": "^18.0.24",
"@types/react-native-pdf-lib": "^0.2.1",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.2.1",
"eslint": "^8.19.0",
"jest": "^29.2.1",
"metro-react-native-babel-preset": "0.73.7",
"prettier": "^2.4.1",
"react-test-renderer": "18.2.0",
"typescript": "4.8.4"
},
"jest": {
"preset": "react-native"
}
}