Skip to content

Commit

Permalink
Added upload image and getting location in postchit.js
Browse files Browse the repository at this point in the history
Implemented get geolocation in postchit.js only a string of coords shows on screen now. Need react-native-maps to picture it then post it to server.
Image upload for chits is complete, but still deciding how to retrieve it and show it in homepage.

Error report:
After installing react-native-geolocation-service, app can't be install in emulator, the error message is: Execution failed for task ':app:processDebugResources'
The solution is go cmd and run these:
1. cd android
2. gradlew.bat clean
Source: oblador/react-native-vector-icons#429

There is also a problem to show picture save through react-native-image-picker, although the base64 string is similar but it doesn't render as expected. Will change back to RNCamera instead if no solution is found.
  • Loading branch information
JerryHwung committed Mar 14, 2020
1 parent 3ea6d94 commit 48aa32c
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 17 deletions.
Binary file added MyApp/MyApp - Shortcut.lnk
Binary file not shown.
13 changes: 13 additions & 0 deletions MyApp/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions MyApp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"react-native": "0.61.5",
"react-native-camera": "^3.19.0",
"react-native-elements": "^1.2.7",
"react-native-geolocation-service": "^4.0.0",
"react-native-gesture-handler": "^1.6.0",
"react-native-image-picker": "^2.3.1",
"react-native-reanimated": "^1.7.0",
Expand Down
2 changes: 1 addition & 1 deletion MyApp/screens/EditPhoto.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class EditPhoto extends Component {
if(this.camera){
const options = {quality: 0.5, base64: true};
const data = await this.camera.takePictureAsync(options);
console.log(data.uri, this.state.token);
console.log(data);

return fetch(baseUrl+'/user/photo',{
method: 'POST',
Expand Down
40 changes: 35 additions & 5 deletions MyApp/screens/HomeScreen.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import React, {Component} from 'react';
import {FlatList, ActivityIndicator, Text, View} from 'react-native';
import {NavigationEvents} from 'react-navigation';
import {ListItem} from 'react-native-elements';
import {ListItem, Image, Card} from 'react-native-elements';
import {baseUrl} from '../components/baseUrl';

const profilePic = require('../images/default.jpg');

// This is the home screen which contains a chit list
class HomeScreen extends Component{
// Constructor to set the states
constructor(props){
super(props);
this.state={
isLodaing: true,
photo: [],
chitListData: []
}
}
Expand All @@ -20,7 +23,6 @@ class HomeScreen extends Component{
.then((response)=> response.json())
.then((responseJson)=>{
this.setState({
isLoading: false,
chitListData: responseJson,
});
})
Expand All @@ -33,6 +35,27 @@ class HomeScreen extends Component{
this.getData()
}

/* getPhoto(chit_id){
fetch(baseUrl+'/chits/'+chit_id+'/photo')
.then((response)=> {
if(response.status=='200'){
return response.blob();
}else{
this.state.photo.push({id: chit_id, source:''})
}
})
.then((image)=>{
var reader = new FileReader();
reader.onload =()=>{
this.state.photo.push({id: chit_id, source: reader.result})
}
reader.readAsDataURL(image);
})
.catch((err)=>{
console.log(err);
});
} */

render(){
// Display activity indicator while waiting data to appear
if(this.state.isLoading){
Expand All @@ -49,15 +72,22 @@ class HomeScreen extends Component{
<FlatList
data={this.state.chitListData}
renderItem={({item}) => (
<ListItem
/* <ListItem
title={item.chit_content}
subtitle={new Date(item.timestamp).toUTCString()}
leftAvatar={{source: profilePic}}
bottomDivider
chevron
onPress={() => console.log("check chit")}
/>
/> */
<Card>
<View>
<Text>{item.chit_content}</Text>
</View>
</Card>

)}
keyExtractor={({chit_id}, index) => chit_id}
keyExtractor={({chit_id}, index) => chit_id.toString()}
/>
</View>
);
Expand Down
140 changes: 131 additions & 9 deletions MyApp/screens/PostChit.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,104 @@
import React, {Component} from 'react';
import {StyleSheet, Text, View, TextInput, AsyncStorage, Alert} from 'react-native';
import {Button} from 'react-native-elements';
import {StyleSheet, Image, Text, View, TextInput, AsyncStorage, Alert, PermissionsAndroid} from 'react-native';
import {Button, Icon} from 'react-native-elements';
import {baseUrl} from '../components/baseUrl'
import ImagePicker from 'react-native-image-picker';
import Geolocation from 'react-native-geolocation-service';

const options = {
title: 'Select Image',
takePhotoButtonTitle: 'Take a photo',
chooseFromLibraryButtonTitle: 'Choose from library',
};
// This screen will contain a textarea to let user create chits
class PostChit extends Component{
// Constructor to set the states
constructor(props){
super(props);
this.state={
userDetails: {},
chitId: '',
auth: {},
image: {},
location: null,
locationPermission: false,
text: '',
numChar: 141
}
}

handleLocation = () => {
if(!this.state.locationPermission){
this.state.locationPermission = requestLocationPermission();
}

Geolocation.getCurrentPosition(
(position) => {
const location = JSON.stringify(position.coords);

this.setState({location});
},
(error)=>{
Alert.alert(error.message)
},
{
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000
}
);
};

handleImage = () => {
ImagePicker.showImagePicker(options,(response)=>{
if(response.didCancel){
console.log('User cancelled');
} else if(response.error){
console.log(response.error);
} else {
let source = {uri: 'data:image/jpeg;base64,'+response.data};

this.setState({
image: source
});
}
})
}

// This async function will get the first chit's id(which is the latest chit)
// then upload the photo to that chit.
async uploadPhoto(){
await this.getChitId(this.state.auth.id)
let chitId = this.state.chitId
let token = this.state.auth.token
await this.postPhoto(token,chitId)
}

postPhoto(token,id){
return fetch(baseUrl+'/chits/'+id+'/photo', {
method: 'POST',
withCredentials: true,
headers: {
'X-Authorization': token,
'Content-Type': 'image/jpeg'
},
body: this.state.image.uri
})
.then((response)=>{
console.log('Picture added!');
console.log(this.state.image.uri);
})
.catch((error)=>{
console.log(error);
});
}

postChit(token,user){
return fetch(baseUrl+'/chits',
{
method: 'POST',
withCredentials: true,
headers: {
'X-Authorization': token,
'X-Authorization': token,
'Content-Type': 'application/json'
},
body: JSON.stringify({
Expand All @@ -33,9 +109,16 @@ class PostChit extends Component{
})
.then((response)=>{
if(response.status == "201"){
// Upload image if the chit post successfully
// and image is not empty object
if(this.state.image != {}){
this.uploadPhoto();
}
Alert.alert("Chit posted successfully!")
this.setState({
text: '',
numChar: 141,
image: {},
});
} else {
Alert.alert("Chit failed to post...")
Expand All @@ -52,17 +135,16 @@ class PostChit extends Component{
this.setState({
auth: authKey
});
this.getData(this.state.auth.id)
}
// A function to do GET/user request to retrieve user details
getData(id){
// Will be changed to 10.0.2.2 in the future for uni
getChitId(id){
return fetch(baseUrl+'/user/' + id)
.then((response)=>response.json())
.then((responseJson)=>{
let id = responseJson.recent_chits[0].chit_id
this.setState({
userDetails: responseJson,
});
chitId : id
})
})
.catch((error)=>{
console.log(error);
Expand All @@ -86,6 +168,20 @@ class PostChit extends Component{
value={this.state.text}
/>
<View style={styles.buttonContainer}>
<Icon
name='image'
type='evilicon'
color='#339aff'
size= {55}
onPress={this.handleImage}
/>
<Icon
name='location'
type='evilicon'
color='#339aff'
size= {55}
onPress={this.handleLocation}
/>
<Text style={styles.counter}>
{this.state.numChar}
</Text>
Expand All @@ -94,6 +190,11 @@ class PostChit extends Component{
onPress={()=> {this.postChit(this.state.auth.token, this.state.userDetails)}}
/>
</View>
<Text>Location: {this.state.location}</Text>
<Image
source={this.state.image}
style={{width: 200, height: 200}}
/>
</View>
);
}
Expand All @@ -113,4 +214,25 @@ const styles = StyleSheet.create({
justifyContent:'flex-end',
},
})

async function requestLocationPermission(){
try {
const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Lab04 Location Permission',
message:'This app requires access to your location.',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('You can access location');
return true;
} else {
console.log('Location permission denied');
return false;
}}
catch (err) {console.warn(err);}
}
export default PostChit
14 changes: 12 additions & 2 deletions MyApp/screens/Profile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, {Component} from 'react';
import {StyleSheet, Alert, Text, View, FlatList, Image, Button, TouchableOpacity, AsyncStorage} from 'react-native';
import {StyleSheet, Alert, Text, View, ActivityIndicator, FlatList, Image, Button, TouchableOpacity, AsyncStorage} from 'react-native';
import {NavigationEvents} from 'react-navigation';
import {ListItem, Avatar} from 'react-native-elements';
import FormButton from '../components/FormButton'
Expand All @@ -13,7 +13,7 @@ class Profile extends Component{
super(props);
this.state={
isLodaing: true,
photo: '',
photo: null,
userDetails: {},
auth:{}
}
Expand Down Expand Up @@ -62,6 +62,7 @@ class Profile extends Component{
isLoading: false,
photo: reader.result
});
console.log(this.state.photo);
}
reader.readAsDataURL(image);
})
Expand All @@ -79,6 +80,15 @@ class Profile extends Component{
}

render(){

// Display activity indicator while waiting data to appear
if(this.state.isLoading){
return(
<View>
<ActivityIndicator/>
</View>
)
}
return(
<View style={{flex: 1}}>
<NavigationEvents onDidFocus={() => this.getUser()}/>
Expand Down
1 change: 1 addition & 0 deletions server/photo_repo/chit5.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified server/photo_repo/user3.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified server/photo_repo/user7.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 48aa32c

Please sign in to comment.