Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fairly Urgent: react-native-image-crop-picker Continually Loading after expo-image-picker #2127

Open
jakeherm opened this issue Jan 15, 2025 · 0 comments

Comments

@jakeherm
Copy link

Version

Tell us which versions you are using:

  • react-native-image-crop-picker v0.41.6
  • react-native v0.76.3

Platform

Tell us to which platform this issue is related

  • iOS

Expected behaviour

I attached two code blocks below. There is a very simple implementation that should shows the most simple situation where this is broken. Then, there is an implementation that contains a "Direct Crop" and a "Select and Crop" that uses the same URI. This proves the issue is not based on the URI. The expected behavior is that the library should finish loading.

Actual behaviour

The actual behavior is that the library continually loads.

Steps to reproduce

  1. Run the below files on iOS Expo and click the button.

Attachments

import React, { useState } from 'react';
import {
  View,
  Text,
  Button,
  StyleSheet,
  ActivityIndicator,
  Alert,
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import ImageCropPicker from 'react-native-image-crop-picker';

export default function App() {
  const [loading, setLoading] = useState(false);
  const [selectedImage, setSelectedImage] = useState(null);
  const [croppedImage, setCroppedImage] = useState(null);

  const handleSelectAndCropPhoto = async () => {
    setLoading(true);
    try {
      // Request permissions
      const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
      if (status !== 'granted') {
        Alert.alert('Permission Required', 'Please grant access to your photo library.');
        setLoading(false);
        return;
      }

      // Open image picker
      const result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ImagePicker.MediaTypeOptions.Images,
        allowsEditing: false,
      });

      if (!result.canceled) {
        const { uri } = result.assets[0];
        console.log(`[App] Selected image URI: ${uri}`);
        setSelectedImage(uri);

        // Open cropper
        const croppedResult = await ImageCropPicker.openCropper({
          path: uri.replace('file://', ''), // Remove file:// prefix
          width: 1000,
          height: 1000,
          cropping: true,
          cropperCircleOverlay: false,
          avoidEmptySpaceAroundImage: true,
          compressImageQuality: 1,
          forceJpg: true,
        });

        console.log(`[App] Cropped image path: ${croppedResult.path}`);
        setCroppedImage(croppedResult.path);
      } else {
        console.log('[App] User canceled image picker.');
      }
    } catch (error) {
      console.error('[App] Error during selection or cropping:', error);
      Alert.alert('Error', 'Something went wrong while selecting or cropping the photo.');
    } finally {
      setLoading(false);
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Image Picker & Cropper Test</Text>
      <Button title="Select and Crop Photo" onPress={handleSelectAndCropPhoto} />
      {loading && <ActivityIndicator size="large" color="#0000ff" style={styles.loader} />}
      {selectedImage && <Text style={styles.info}>Selected Image: {selectedImage}</Text>}
      {croppedImage && <Text style={styles.info}>Cropped Image: {croppedImage}</Text>}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  info: {
    marginTop: 20,
    textAlign: 'center',
    fontSize: 16,
  },
  loader: {
    marginTop: 20,
  },
});
import React, { useState } from 'react';
import {
  View,
  Text,
  Button,
  StyleSheet,
  ActivityIndicator,
  Alert,
  Platform,
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import ImageCropPicker from 'react-native-image-crop-picker';

export default function App() {
  const [loading, setLoading] = useState(false);
  const [selectedImage, setSelectedImage] = useState(null);
  const [croppedImage, setCroppedImage] = useState(null);

  const handleSelectAndCropPhoto = async () => {
    try {
      setLoading(true);
      
      // Request permissions
      const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
      if (status !== 'granted') {
        Alert.alert('Permission Required', 'Please grant access to your photo library.');
        return;
      }

      // First use Expo ImagePicker for selection
      const result = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ImagePicker.MediaTypeOptions.Images,
        allowsEditing: false,
        quality: 1,
      });

      if (result.canceled) {
        console.log('[App] User canceled image picker');
        setLoading(false);
        return;
      }

      const { uri } = result.assets[0];
      console.log(`[App] Selected image URI: ${uri}`);
      setSelectedImage(uri);

      // Try with static path first for testing
      const testPath = '/var/mobile/Containers/Data/Application/662861CC-0AB0-4074-89FD-E02D16ED27E2/Library/Caches/ImagePicker/C4867544-0BEA-41EC-804A-6256352D0643.png';

      console.log('[App] Attempting to crop with path:', testPath);

      // Then use react-native-image-crop-picker for cropping
      const croppedResult = await ImageCropPicker.openCropper({
        path: testPath,
        width: 1000,
        height: 1000,
        cropping: true,
        cropperCircleOverlay: false,
        avoidEmptySpaceAroundImage: true,
        compressImageQuality: 1,
        forceJpg: true,
        mediaType: 'photo',
      }).catch(error => {
        console.error('[App] Cropping error:', error);
        throw error;
      });

      if (croppedResult) {
        console.log(`[App] Cropped image path: ${croppedResult.path}`);
        setCroppedImage(croppedResult.path);
      }

    } catch (error) {
      console.error('[App] Error details:', error);
      Alert.alert('Error', `Failed to process image: ${error.message}`);
    } finally {
      setLoading(false);
    }
  };

  // Added a direct crop test function
  const testDirectCrop = async () => {
    try {
      setLoading(true);
      const staticPath = Platform.OS === 'ios' 
        ? '/var/mobile/Containers/Data/Application/662861CC-0AB0-4074-89FD-E02D16ED27E2/Library/Caches/ImagePicker/C4867544-0BEA-41EC-804A-6256352D0643.png'
        : '/storage/emulated/0/DCIM/Camera/test.jpg'; // Example Android path

      console.log('[App] Testing direct crop with path:', staticPath);

      const croppedResult = await ImageCropPicker.openCropper({
        path: staticPath,
        width: 1000,
        height: 1000,
        cropping: true,
        cropperCircleOverlay: false,
        avoidEmptySpaceAroundImage: true,
        compressImageQuality: 1,
        forceJpg: true,
        mediaType: 'photo',
      });

      console.log('[App] Direct crop result:', croppedResult);
      setCroppedImage(croppedResult.path);
    } catch (error) {
      console.error('[App] Direct crop error:', error);
      Alert.alert('Error', `Direct crop failed: ${error.message}`);
    } finally {
      setLoading(false);
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Image Picker & Cropper Test</Text>
      <Button 
        title="Select and Crop Photo" 
        onPress={handleSelectAndCropPhoto}
        disabled={loading}
      />
      <Button 
        title="Test Direct Crop" 
        onPress={testDirectCrop}
        disabled={loading}
      />
      {loading && <ActivityIndicator size="large" color="#0000ff" style={styles.loader} />}
      {selectedImage && (
        <Text style={styles.info}>
          Selected Image: {selectedImage}
        </Text>
      )}
      {croppedImage && (
        <Text style={styles.info}>
          Cropped Image: {croppedImage}
        </Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  info: {
    marginTop: 20,
    textAlign: 'center',
    fontSize: 16,
  },
  loader: {
    marginTop: 20,
  },
});

// stacktrace or any other useful debug info

Love react-native-image-crop-picker? Please consider supporting our collective:
👉 https://opencollective.com/react-native-image-crop-picker/donate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant