react-native-image-crop-tools CropView not showing image to be cropped - react-native

I am using react-native-image-crop-tools for cropping the image but CropView not showing the image to be cropped only a blank screen is showing. any solution regarding this?
import { CropView } from 'react-native-image-crop-tools';
const [uri, setUri] = useState('https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg');
{uri !== undefined && <CropView
sourceUrl={uri}
style={{flex:1}}
ref={cropViewRef}
onImageCrop={(res) => console.warn(res)}
keepAspectRatio
aspectRatio={{ width: 16, height: 9 }}
/>}

Try this, I hope it will help you.
app.js
import React, { useState, useRef } from 'react';
import { Button, StyleSheet, View} from 'react-native';
import { CropView } from 'react-native-image-crop-tools';
import { launchImageLibrary } from 'react-native-image-picker';
export default function app() {
const [uri, setUri] = useState();
const cropViewRef = useRef();
let options = {
mediaType: 'photo',
quality: 1,
};
return (
<>
<View style={styles.container}>
<Button
title={'Pick Image'}
onPress={() => {
launchImageLibrary(options, response => {
setUri(response.assets[0].uri);
});
}}
/>
{uri !== undefined && <CropView
sourceUrl={uri}
style={styles.cropView}
ref={cropViewRef}
onImageCrop={(res) => console.log(res)}
keepAspectRatio
aspectRatio={{ width: 16, height: 9 }}
/>}
<Button
title={'Get Cropped View'}
onPress={() => {
cropViewRef.current.saveImage(true, 100);
}}
/>
</View>
</>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
cropView: {
flex: 1,
backgroundColor: '#000'
},
});

The library doesn't support remote images. It working in iOS is merely coincidental as might the native ios library supports for the cropping of network images.
If you want to crop a remote image please download it first using RNFetchBlob and then pass the local file path to it.
Supporting remote images directly is a somewhat complicated task and out of scope for this project.
You also can check out the closed issue in the library.
https://github.com/hhunaid/react-native-image-crop-tools/issues/16
You can have a try with the below example to crop the network images in the android platform:
For ex:
import React, {useCallback, useEffect, useState} from 'react';
import {View, Text} from 'react-native';
import {CropView} from 'react-native-image-crop-tools';
import RNFetchBlob from 'rn-fetch-blob';
export default () => {
const [uri, setUri] = useState('');
const getImage = useCallback(() => {
try {
RNFetchBlob.config({
fileCache: true,
// by adding this option, the temp files will have a file extension
appendExt: 'png',
})
.fetch(
'GET',
'https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__480.jpg',
)
.then(res => {
let status = res.info().status;
if (status === 200) {
setUri('file://' + res.path());
} else {
console.log(status);
}
})
// Something went wrong:
.catch((errorMessage, statusCode) => {
// error handling
console.log('Error : ', errorMessage);
});
} catch (err) {
console.log('Error : ', err.message);
}
}, []);
useEffect(() => {
getImage();
}, [getImage]);
if (uri === '') {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<Text>{'processing...'}</Text>
</View>
);
}
return (
<CropView
sourceUrl={uri}
style={{flex: 1, height: '100%', width: '100%'}}
// ref={cropViewRef}
onImageCrop={res => console.warn(res)}
keepAspectRatio
aspectRatio={{width: 16, height: 9}}
/>
);
};

Related

I want to make a bottom bar

I want to make lower under the bar.But I don't know how to make. Press the lower bar to help me seyeo can get a page, I want I want to make.And I want to put the image that I want in the bottom bar Tell me what to do first I need your help I searched hard on Google, but there is no code similar to mine, so I keep getting it wrong or weird
import React, { useRef, useState, useCallback, useEffect } from 'react';
import {
View,
BackHandler,
Platform,
StyleSheet,
ActivityIndicator,
} from 'react-native';
import { WebView } from 'react-native-webview';
import { Image } from "react-native";
const DELAY_BEFORE_WEBVIEW = 10; // <--- seconds before webview load
export default function App() {
// ref
const webView = useRef();
const [canGoBack, setCanGoBack] = useState(false);
const handleBack = useCallback(() => {
if (canGoBack && webView.current) {
webView.current.goBack();
return true;
}
return false;
}, [canGoBack]);
// effects
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', handleBack);
return () => {
BackHandler.removeEventListener('hardwareBackPress', handleBack);
};
}, [handleBack]);
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 1000 * DELAY_BEFORE_WEBVIEW);
}, []);
// states
const [isLoading, setIsLoading] = useState(true);
return (
<View style={styles.container}>
<WebView
ref={webView}
source={{ uri: 'https://www.talesrunnerbestguild.co.kr/' }}
style={styles.webView}
onLoadProgress={(event) => setCanGoBack(event.nativeEvent.canGoBack)}
/>
{isLoading && <CenterLoader />}
</View>
);
}
const CenterLoader = () => (
<View style={styles.loaderContainer}>
<Image source={require('/workspace/talesrunner23/assets/js34.png/')}
style={{height:115,width:90}}/>
</View>
);
const styles = StyleSheet.create({
container: { flex: 1 },
loaderContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
width: '100%',
height: '100%',
backgroundColor:'white' // <-- comment this to show webview while loading
},
webView:
Platform.OS === 'ios'
? { marginTop: 30, marginBottom: 40 }
: { marginTop: 30 },
});

I want to make a bottom bar The bottom bar goes to the page I want when I click it

enter image description here
I want to make a bottom bar The bottom bar goes to the page I want when I click it
I want to make it similar to that picture
I want to make a bottom bar like that
I've been googling hard, but I can't find anything similar to me
https://reactnavigation.org/docs/bottom-tab-navigator/
I want to use the code in the address over there, but I don't know
import React, { useRef, useState, useCallback, useEffect } from
'react';
import {
View,
BackHandler,
Platform,
StyleSheet,
ActivityIndicator,
} from 'react-native';
import { WebView } from 'react-native-webview';
import { Image } from "react-native";
const DELAY_BEFORE_WEBVIEW = 10; // <--- seconds before webview load
export default function App() {
// ref
const webView = useRef();
const [canGoBack, setCanGoBack] = useState(false);
const handleBack = useCallback(() => {
if (canGoBack && webView.current) {
webView.current.goBack();
return true;
}
return false;
}, [canGoBack]);
// effects
useEffect(() => {
BackHandler.addEventListener('hardwareBackPress', handleBack);
return () => {
BackHandler.removeEventListener('hardwareBackPress', handleBack);
};
}, [handleBack]);
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 1000 * DELAY_BEFORE_WEBVIEW);
}, []);
// states
const [isLoading, setIsLoading] = useState(true);
return (
<View style={styles.container}>
<WebView
ref={webView}
source={{ uri: 'https://www.talesrunnerbestguild.co.kr/' }}
style={styles.webView}
onLoadProgress={(event) =>
setCanGoBack(event.nativeEvent.canGoBack)}
/>
{isLoading && <CenterLoader />}
</View>
);
}
const CenterLoader = () => (
<View style={styles.loaderContainer}>
<Imagesource{require('/workspace/talesrunner23/assets/js34.png/')}
style={{height:115,width:90}}/>
</View>
);
const styles = StyleSheet.create({
container: { flex: 1 },
loaderContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
width: '100%',
height: '100%',
backgroundColor:'white' // <-- comment this to show webview while
loading
},
webView:
Platform.OS === 'ios'
? { marginTop: 30, marginBottom: 40 }
: { marginTop: 30 },
});

Amplify Tutorial (Expo) and got error message on signin

I'm doing this tutorial: https://docs.amplify.aws/start/getting-started/auth/q/integration/react-native#create-login-ui
I followed it completely and did everything they told me to do. The Todo works, but when I added Auth, and wrapped it. The project will start. Users can create accounts. But when you try to sign in on iOS it won't work. Strangely, when I tested it on web, users could sign in. Leading me to think it is a problem with iOS. I tested it on my iPhone with expo installed and it failed there too.
Here is a link to my issue: https://github.com/aws-amplify/amplify-js/issues/8113#issuecomment-830995508
This is my app.js
import config from './aws-exports'
Amplify.configure(config)
import { withAuthenticator } from 'aws-amplify-react-native'
import React, { useEffect, useState } from 'react'
import {
View, Text, StyleSheet, TextInput, Button
} from 'react-native'
import { API, graphqlOperation } from 'aws-amplify'
import { createTodo } from './graphql/mutations'
import { listTodos } from './graphql/queries'
const initialState = { name: '', description: '' }
const App = () => {
const [formState, setFormState] = useState(initialState)
const [todos, setTodos] = useState([])
useEffect(() => {
fetchTodos()
}, [])
function setInput(key, value) {
setFormState({ ...formState, [key]: value })
}
async function fetchTodos() {
try {
const todoData = await API.graphql(graphqlOperation(listTodos))
const todos = todoData.data.listTodos.items
setTodos(todos)
} catch (err) { console.log('error fetching todos') }
}
async function addTodo() {
try {
const todo = { ...formState }
setTodos([...todos, todo])
setFormState(initialState)
await API.graphql(graphqlOperation(createTodo, {input: todo}))
} catch (err) {
console.log('error creating todo:', err)
}
}
return (
<View style={styles.container}>
<TextInput
onChangeText={val => setInput('name', val)}
style={styles.input}
value={formState.name}
placeholder="Name"
/>
<TextInput
onChangeText={val => setInput('description', val)}
style={styles.input}
value={formState.description}
placeholder="Description"
/>
<Button title="Create Todo" onPress={addTodo} />
{
todos.map((todo, index) => (
<View key={todo.id ? todo.id : index} style={styles.todo}>
<Text style={styles.todoName}>{todo.name}</Text>
<Text>{todo.description}</Text>
</View>
))
}
</View>
)
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', padding: 20 },
todo: { marginBottom: 15 },
input: { height: 50, backgroundColor: '#ddd', marginBottom: 10, padding: 8 },
todoName: { fontSize: 18 }
})
export default withAuthenticator(App)```
I feel like the problem might be with the ./aws-exports potentially. There was a bug where you had to move it out of src, etc. Anyone have any ideas?
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/1Wt6J.png
I found out that the login error was due to a bug with expo deprecating a file. See this issue for more. https://github.com/aws-amplify/amplify-js/issues/8113#issuecomment-830995508

React Native, how to execute a component's method from App.js when using stack navigation

I finished a React Native course, and I'm trying to make a chat app to practice.
Summarize the problem:
I have 2 screens ,ContactList.js and ChatRoom.js
I have a Navigation stack with these two screens Navigation.js
The Navigation component is imported and rendered in App.js
I added FCM module to handle notifications
The goal is to execute the function that loads messages in the chatroom _loadMessages(), when the app receives a notification on foreground state. And to execute the function (I didn't create it yet) to update unread message in a global state.
What I've tried
I followed react native firebase docs, I have a function that handle notification on foreground declared inside App.js. The problem is that I can't tell the other components (the screens) to execute their functions. The "Ref" method can't be used cause I'm not calling the child component (the screens) directly inside the App.js, I'm calling and rendering the Navigation.js Stack instead.
So, in this case, when we have a navigation component called on app.js, how can we tell other components to execute a function that is declared inside them?
App.js
import React, { useEffect } from 'react'
import Navigation from './Navigation/Navigation'
import messaging from '#react-native-firebase/messaging';
export default function App() {
requestUserPermission = async () => {
//On récupere le token
const token = await messaging().getToken();
console.log('TOKEN: ' + token)
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
console.log('Authorization status:', authStatus);
}
}
handleForegroundNotification = () => {
const unsubscribe = messaging().onMessage(async remoteMessage => {
console.log('A new FCM message arrived!', JSON.stringify(remoteMessage));
});
return unsubscribe;
}
useEffect(() => {
this.requestUserPermission();
this.handleForegroundNotification();
}, []);
return (
<Navigation />
)
}
Navigation.js
import { createAppContainer } from "react-navigation"
import { createStackNavigator } from "react-navigation-stack"
import ContactList from '../Components/ContactList'
import ChatRoom from '../Components/ChatRoom'
const ChatStackNavigator = createStackNavigator({
ContactList: {
screen: ContactList,
navigationOptions: {
title: 'Contacts'
}
},
ChatRoom: {
screen: ChatRoom,
navigationOptions: {
title: 'Conversation'
}
}
})
export default createAppContainer(ChatStackNavigator)
ChatRoom.js
import React from 'react'
import { View, StyleSheet, Text, Image, SafeAreaView, TextInput, Alert, FlatList, ActivityIndicator } from 'react-native'
import { sendMessage } from '../API/sendMessageApi'
import { getMessages } from '../API/getMessagesApi'
import MessageItem from './MessageItem'
class ChatRoom extends React.Component {
constructor(props) {
super(props)
this.message = ""
this.contact = this.props.navigation.getParam('contact')
this.state = {
defautInputValue: "",
listMessages: [],
isLoading: true
}
}
_textInputChanged(text) {
this.message = text
}
_sendMessage() {
this.setState({ defautInputValue: " " });
sendMessage('1', this.contact.id_contact, this.message).then(() => {
this._loadMessages();
});
}
_loadMessages() {
getMessages('1', this.contact.id_contact).then((data) => {
this.setState({ listMessages: data, isLoading: false, defautInputValue: "" })
});
}
componentDidMount() {
this._loadMessages();
}
_displayLoading() {
if (this.state.isLoading) {
return (
<View style={[styles.loading_container]}>
<ActivityIndicator size="large" color="orange" />
</View>
)
}
}
render() {
//console.log('Contact ID: ' + JSON.parse(this.contact))
return (
<SafeAreaView style={styles.container}>
<View style={styles.contact}>
<View style={styles.image_container}>
<Image
style={styles.image}
source={{ uri: 'https://moonchat.imedramdani.com/avatar/' + this.contact.avatar }}
></Image>
</View>
<View style={styles.username_container}>
<Text style={styles.username}>{this.contact.username}</Text>
</View>
</View>
{/* BODY */}
<View style={styles.body}>
<FlatList
ref={ref => this.flatList = ref}
onContentSizeChange={() => this.flatList.scrollToEnd({ animated: true })}
data={this.state.listMessages}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) =>
<MessageItem
message={item}
/>}
>
</FlatList>
</View>
<View style={styles.input_container}>
<TextInput
style={styles.input}
onChangeText={(text) => this._textInputChanged(text)}
onSubmitEditing={() => this._sendMessage()}
defaultValue={this.state.defautInputValue}
placeholder="Aa"
></TextInput>
</View>
{this._displayLoading()}
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#1d2733',
},
contact: {
height: 50,
backgroundColor: '#1d2733',
marginTop: 0,
flexDirection: 'row',
borderBottomColor: 'grey',
borderWidth: 1
},
username_container: {
//backgroundColor: 'red',
flex: 3,
justifyContent: 'center',
alignItems: 'flex-start'
},
username: {
fontSize: 20,
color: 'white'
},
image_container: {
//backgroundColor: 'blue',
flex: 1,
justifyContent: 'center'
},
image: {
//backgroundColor: 'yellow',
height: 45,
width: 45,
marginLeft: 10,
borderRadius: 25
},
body: {
//backgroundColor: 'red',
flex: 1
},
input_container: {
height: 75,
//backgroundColor:'blue',
padding: 5
},
input: {
paddingLeft: 20,
height: 50,
backgroundColor: 'white',
borderWidth: 1,
borderRadius: 25,
borderColor: '#D5D5D5',
fontSize: 20
},
loading_container: {
position: 'absolute',
left: 0,
right: 0,
top: 0,
bottom: 0,
alignItems: 'center',
justifyContent: 'center'
},
});
export default ChatRoom
Thanks!
I set up a solution that worked, but I don't know if it is a proper way.
I restored App.js
import React from 'react'
import Root from './Root'
import { Provider } from 'react-redux'
import Store from './Store/configureStore'
class App extends React.Component {
render() {
return (
<Provider store={Store}>
<Root />
</Provider>
)
}
}
export default App
I created a now component Root.js which contains notification handler
import React from 'react'
import Navigation from './Navigation/Navigation'
import messaging from '#react-native-firebase/messaging'
import { connect } from 'react-redux'
class Root extends React.Component {
requestUserPermission = async () => {
//On récupere le token
const token = await messaging().getToken();
console.log('TOKEN: ' + token)
const authStatus = await messaging().requestPermission();
const enabled =
authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (enabled) {
console.log('Authorization status:', authStatus);
}
}
handleForegroundNotification = () => {
const unsubscribe = messaging().onMessage(async remoteMessage => {
console.log('A new FCM message arrived!', JSON.stringify(remoteMessage));
const action = { type: "RELOAD_MESSAGES", value: '1' }
this.props.dispatch(action)
});
return unsubscribe;
}
componentDidMount() {
this.requestUserPermission();
this.handleForegroundNotification();
}
render() {
return (
<Navigation />
)
}
}
const mapStateToProps = (state) => {
return {
loadyourself: state.loadyourself
}
}
export default connect(mapStateToProps)(Root)
The store is provided in App.js to let Root.js access the global state.
When a notification is received at foreground, the Root.js update a key in the global state named "loadyourself". When the state is updated, the ChatRoom.js which is connected to the store too, trigger the componentDidUpdate()
componentDidUpdate() {
if (this.props.loadyourself == "1") {
this._reloadMessages();
}
}
of course, to avoid the infinite loop, the _reloadMessages() restore default value in the global state of loadyourself key
_reloadMessages() {
const action = { type: "RELOAD_MESSAGES", value: '0' }
this.props.dispatch(action)
getMessages('1', this.contact.id_contact).then((data) => {
this.setState({ listMessages: data })
});
}
The messages are updated, the global state is re-initialized, the componentDidUpdate() does not trigger until next notification.
It works. Like I said, I don't know if there is a more proper way, I'm new in React-Native (2 weeks). I am open to other solutions

React Native - How to extract data from FaceDetector of Expo SDK?

I’m new to React Native and still learning React and JavaScript. I’m practicing on Expo snack with Expo's FaceDetector (SDK 37) and managed to generate data about faces. However, I couldn't (or don't know how to) extract these data. My goal for now is to render the rollAngle data in a Text component.
Here is the code I used in Expo Snack and tested with my Android cellphone:
import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';
import { Camera } from 'expo-camera';
import * as FaceDetector from 'expo-face-detector'
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [faces, setFaces] = useState([])
const faceDetected = ({faces}) => {
setFaces({faces})
console.log({faces})
}
useEffect(() => {
(async () => {
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
if (hasPermission !== true) {
return <Text>No access to camera</Text>
}
return (
//<View style={{ flex: 1 }}>
<Camera
style={{ flex: 1 }}
type='front'
onFacesDetected = {faceDetected}
FaceDetectorSettings = {{
mode: FaceDetector.Constants.Mode.fast,
detectLandmarks: FaceDetector.Constants.Landmarks.all,
runClassifications: FaceDetector.Constants.Classifications.none,
minDetectionInterval: 5000,
tracking: false
}}
>
<View
style={{
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
}}>
<Text style= {{top:200}}> is {faces[0].rollAngle} </Text>
</View>
</Camera>
//</View>
);
}
In the snack console, I see results like this:
Results in the Snack console
I tried to replace the faceDetected function with the following code:
const faceDetected = (faces) => {
setFaces(faces)
console.log(faces)
}
Then, the console shows slightly different results: Results in Snack console
I tried both ways to render rollAngle, but an error message showed up and said face[0].rollAngle is undefined and is not an object.
Please help and any suggestion is appreciated.
Thank you.
You may have resolved this problem.
"faces.faces" worked for me..
const faceDetected = (faces) => {
setFaces(faces.faces)
}
I am new to react-native..
So if you resolved it by some other way please let us know.
I believe I have fixed your problem:
import React, { useState, useEffect } from 'react';
import { Text, View } from 'react-native';
import { Camera } from 'expo-camera';
import * as FaceDetector from 'expo-face-detector'
export default function App() {
const [hasPermission, setHasPermission] = useState(null);
const [faces, setFaces] = useState([])
const faceDetected = ({faces}) => {
setFaces(faces) // instead of setFaces({faces})
console.log({faces})
}
useEffect(() => {
(async () => {
const { status } = await Camera.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
if (hasPermission !== true) {
return <Text>No access to camera</Text>
}
return (
//<View style={{ flex: 1 }}>
<Camera
style={{ flex: 1 }}
type='front'
onFacesDetected = {faceDetected}
FaceDetectorSettings = {{
mode: FaceDetector.Constants.Mode.fast,
detectLandmarks: FaceDetector.Constants.Landmarks.all,
runClassifications: FaceDetector.Constants.Classifications.none,
minDetectionInterval: 5000,
tracking: false
}}
>
<View
style={{
flex: 1,
backgroundColor: 'transparent',
flexDirection: 'row',
}}>
{faces[0] && <Text style= {{top:200}}> is {faces[0].rollAngle} </Text>} // only render text if faces[0] exists
</View>
</Camera>
//</View>
);
}
I think your main problem was you were using
setFaces({faces})
instead of
setFaces(faces)