Skip to content

Instantly share code, notes, and snippets.

@parappathekappa
Last active January 24, 2018 18:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save parappathekappa/000cb565c7bfc57fb3821a07ec7405c6 to your computer and use it in GitHub Desktop.
Save parappathekappa/000cb565c7bfc57fb3821a07ec7405c6 to your computer and use it in GitHub Desktop.
import React, { Component } from "react";
import {
ActivityIndicator,
FlatList,
StatusBar,
Text,
TouchableHighlight,
View
} from "react-native";
import EStyleSheet from "react-native-extended-stylesheet";
import PropTypes from "prop-types";
import { Location, Permissions } from "expo";
import { ListItem, Separator } from "../components/List";
import { connect } from "react-redux";
import { selectAddress } from "../actions/postcard";
import { compareString } from "../utils/compareString";
import { setLocation } from "../actions/postcard";
import { setAddresses } from "../actions/postcard";
import { clearLocation } from "../actions/postcard";
import { clearAddresses } from "../actions/postcard";
import { setExpoAddresses } from "../actions/postcard";
class AddressList extends Component {
static PropTypes = {
navigation: PropTypes.object,
addresses: PropTypes.array
};
state = {
loading: true,
location: null,
addresses: []
};
componentWillMount() {
this.masterFunction();
}
handlePress = address => {
if (!this.props.options.house) {
this.props.dispatch(selectAddress(address));
}
this.props.navigation.navigate("Preview", { title: "Preview" });
};
// filters out duplicate addresses
filterAddresses(addresses) {
return this.unique(addresses);
}
unique(array) {
return array.reduce(function(result, object) {
if (
!result.find(function(item) {
return item.number === object.number;
})
) {
result.push(object);
}
return result;
}, []);
}
masterFunction = async () => {
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== "granted") {
this.setState({
errorMessage: "Permission to access location was denied"
});
}
let location = await Location.getCurrentPositionAsync({
enableHighAccuracy: true
});
if (location.coords.accuracy <= 10) {
this.props.dispatch(clearLocation());
this.props.dispatch(clearAddresses());
this.props.dispatch(setLocation(location));
this.getAddresses(location);
} else {
this.masterFunction();
}
};
getAddresses = location => {
Location.reverseGeocodeAsync({
latitude: location.coords.latitude,
longitude: location.coords.longitude
}).then(response => {
console.log("RESPONSE:", response);
this.props.dispatch(setExpoAddresses(response));
}).then(response => {
this.getAddressesFromApi(
location.coords.latitude,
location.coords.longitude
);
}).then(response => {
this.getMultipleAddressesFromApi(location);
}).then(response => {
this.pickAddy();
});
};
getAddressesFromApi = (latitude, longitude) => {
return fetch("https://miserywhip.com/v1/locate", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
lat: latitude,
lng: longitude
})
})
.then(response => response.json())
.then(responseJson => {
console.log(responseJson);
this.props.dispatch(setAddresses(responseJson.addresses));
})
.catch(error => {
console.error(error);
});
};
// Hack attack. Move the point around and hit api several times
// Remove duplicate addresses from the array
// Hold list of lat lng points
getMultipleAddressesFromApi = location => {
pointsHolder = [];
// Earth's radius
R = 6371000;
// Array of radians
radiansArray = [0, 1.57, 3.14, 4.71];
// Distance between points
d = 15;
// add original lat lng values from location
mylat = location.coords.latitude;
mylon = location.coords.longitude;
pointsHolder.push([mylat, mylon]);
// cycle through radiansArray to generate new points
for (i = 0; i < radiansArray.length; i++) {
brng = radiansArray[i];
mylatrad = mylat * Math.PI / 180;
mylonrad = mylon * Math.PI / 180;
var newlatrad = Math.asin(
Math.sin(mylatrad) * Math.cos(d / R) +
Math.cos(mylatrad) * Math.sin(d / R) * Math.cos(brng)
);
var newlonrad =
mylonrad +
Math.atan2(
Math.sin(brng) * Math.sin(d / R) * Math.cos(mylatrad),
Math.cos(d / R) - Math.sin(mylatrad) * Math.sin(newlatrad)
);
newlat = newlatrad / Math.PI * 180;
newlon = newlonrad / Math.PI * 180;
pointsHolder.push([newlat, newlon]);
}
for (i = 0; i < 5; i++) {
this.getAddressesFromApi(pointsHolder[i][0], pointsHolder[i][1]);
}
this.pickAddy();
};
theone = new String();
pickAddy() {
// only do this if the user has entered a house number
// in the options form
if (this.props.options.house) {
var myNewAddy = {};
var hnum = Number(this.props.options.house);
// Cycle through each address in the list
// Find the one that is correct, update selectedAddress
for (i = 0; i < this.props.addresses.length; i++) {
var addy = String(this.props.addresses[i].number);
if (compareString(addy, hnum)) {
this.theone = this.props.addresses[i].number;
myNewAddy = Object.assign({}, this.props.addresses[i]);
myNewAddy.number = this.props.options.house;
this.props.dispatch(selectAddress(myNewAddy));
console.log("Selected this address from the list.");
console.log(myNewAddy);
return;
}
}
// If none of the address list options were correc
// Check the expo returned address
for (i = 0; i < this.props.expoAddresses.length; i++) {
var bigaddy = String(this.props.expoAddresses[i].name);
var newind = bigaddy.indexOf(' ');
var expoaddy = bigaddy.slice(0, newind);
if (compareString(expoaddy, hnum)) {
this.theone = this.props.expoAddresses[i].name;
myNewAddy = Object.assign({}, this.props.expoAddresses[i]);
this.props.dispatch(selectAddress(myNewAddy));
console.log("Selected this address from expo.");
console.log(myNewAddy);
return;
}
}
// If no hits, just return nothing
return;
}
}
render() {
if (this.props.addresses.length < 1) {
return (
<ActivityIndicator animating size="large" style={{ padding: 20 }} />
);
}
return (
<View style={styles.container}>
<StatusBar barStyle="default" translucent={false} />
<FlatList
data={this.props.expoAddresses}
renderItem={({ item }) => (
<ListItem
text={item.name}
selected={item.name === this.theone}
onPress={() => this.handlePress(item)}
/>
)}
keyExtractor={(item, index) => index}
ItemSeparatorComponent={Separator}
/>
<FlatList
data={this.filterAddresses(this.props.addresses)}
renderItem={({ item }) => (
<ListItem
text={item.number + " " + item.street}
selected={item.number === this.theone}
onPress={() => this.handlePress(item)}
/>
)}
keyExtractor={(item, index) => index}
ItemSeparatorComponent={Separator}
/>
<TouchableHighlight
style={styles.debugging}
onPress={() => this.masterFunction()}
>
<Text>REFRESH</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.debugging}
onPress={() => alert(JSON.stringify(this.props.addresses))}
>
<Text>View All Addresses Returned</Text>
</TouchableHighlight>
</View>
);
}
}
const mapStateToProps = state => {
const addresses = state.postcard.addresses;
const expoAddresses = state.postcard.expoAddresses;
const options = state.postcard.options;
const selectedAddress = state.postcard.selectedAddress;
return {
addresses,
expoAddresses,
options,
selectedAddress
};
};
const styles = EStyleSheet.create({
container: {
flex: 1,
paddingTop: 30,
justifyContent: "flex-start"
},
debugging: {
padding: 5,
paddingBottom: 20,
alignItems: "center"
}
});
export default connect(mapStateToProps)(AddressList);
import React, { Component } from "react";
import {
ActivityIndicator,
FlatList,
StatusBar,
Text,
TouchableHighlight,
View
} from "react-native";
import EStyleSheet from "react-native-extended-stylesheet";
import PropTypes from "prop-types";
import { Location, Permissions } from "expo";
import { ListItem, Separator } from "../components/List";
import { connect } from "react-redux";
import { selectAddress } from "../actions/postcard";
import { pickAddy } from "../utils/pickAddy";
import { getLocationAsync } from "../utils/getLocationAsync";
import { getMultipleAddressesFromApi } from "../utils/getMultipleAddressesFromApi";
import {
setLocation,
setAddresses,
clearLocation,
clearAddresses,
setExpoAddresses,
setAddressStatus
} from "../actions/postcard";
class AddressList extends Component {
static PropTypes = {
navigation: PropTypes.object,
addresses: PropTypes.array
};
state = {
loading: true,
location: null,
addresses: []
};
componentWillMount() {
// Clear cache and get users location
this.masterFunction();
}
handlePress = address => {
if (!this.props.options.house) {
this.props.dispatch(selectAddress(address));
}
this.props.navigation.navigate("Preview", { title: "Preview" });
};
// filters out duplicate addresses
filterAddresses(addresses) {
return this.unique(addresses);
}
unique(array) {
return array.reduce(function(result, object) {
if (
!result.find(function(item) {
return item.number === object.number;
})
) {
result.push(object);
}
return result;
}, []);
}
masterFunction = () => {
// Clear Cache
this.props.dispatch(clearLocation());
this.props.dispatch(clearAddresses());
this.props.dispatch(setAddressStatus("Finding your location..."));
// Get the users location
this.getAddresses();
}
getAddresses = () => {
// Get the users location
let myLocation = getLocationAsync()
.then(location => {
if (location.coords.accuracy <= 1000) {
console.log("Accuracy Reached!");
this.props.dispatch(setLocation(location));
this.props.dispatch(setAddressStatus("Loading Address List..."));
// Get the expo address
Location.reverseGeocodeAsync({
latitude: location.coords.latitude,
longitude: location.coords.longitude
}).then(response => {
// Update the state with Expo Address
console.log("Expo Address Returned");
this.props.dispatch(setExpoAddresses(response));
}).catch(error => {
console.error(error);
});
// Get multiple addresses from the api using a hack method
// of moving a point around a bunch of times
getMultipleAddressesFromApi(
location
).then(masterlist => {
// Update the state with list from API
console.log("API Addresses Returned");
this.props.dispatch(setAddresses(masterlist));
}).then(() => {
// Select the correct addy from the list
var selectedAddy = pickAddy(
this.props.options.house,
this.props.expoAddresses,
this.props.addresses
);
this.props.dispatch(selectAddress(selectedAddy.myNewAddy));
this.theone = selectedAddy.theone;
this.props.dispatch(setAddressStatus("All loaded!"));
}).catch(error => {
console.error(error);
});
} else {
console.log("Accuracy: " + location.coords.accuracy);
// Repeat every second until the accuracy threshold is reached
setTimeout(() => {
this.getAddresses();
}, 1000);
}
})
};
theone = new String();
render() {
// Spinning icon for waiting for the list
// if (this.props.addresses.length < 1 || this.props.expoAddresses.length < 1) {
// return (
// <ActivityIndicator animating size="large" style={{ padding: 20 }} />
// );
// }
return (
<View style={styles.container}>
<StatusBar barStyle="default" translucent={false} />
{/* Status message */}
<Text>
{this.props.addressStatus}
</Text>
<FlatList
data={this.filterAddresses(this.props.expoAddresses)}
renderItem={({ item }) => (
<ListItem
text={item.name}
selected={item.name === this.theone}
onPress={() => this.handlePress(item)}
/>
)}
keyExtractor={(item, index) => index}
ItemSeparatorComponent={Separator}
/>
<FlatList
data={this.filterAddresses(this.props.addresses)}
// data={this.props.addresses}
renderItem={({ item }) => (
<ListItem
text={item.number + " " + item.street}
selected={item.number === this.theone}
onPress={() => this.handlePress(item)}
/>
)}
keyExtractor={(item, index) => index}
ItemSeparatorComponent={Separator}
/>
<TouchableHighlight
style={styles.debugging}
// onPress={() => this.getLocationAsync()}
onPress={() => this.masterFunction()}
>
<Text>REFRESH</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.debugging}
onPress={() => alert(JSON.stringify(this.props.addresses))}
>
<Text>View All Addresses Returned</Text>
</TouchableHighlight>
</View>
);
}
}
const mapStateToProps = state => {
const addresses = state.postcard.addresses;
const expoAddresses = state.postcard.expoAddresses;
const options = state.postcard.options;
const selectedAddress = state.postcard.selectedAddress;
const addressStatus = state.postcard.addressStatus;
return {
addresses,
expoAddresses,
options,
selectedAddress,
addressStatus
};
};
const styles = EStyleSheet.create({
container: {
flex: 1,
paddingTop: 30,
justifyContent: "flex-start"
},
debugging: {
padding: 5,
paddingBottom: 20,
alignItems: "center"
}
});
export default connect(mapStateToProps)(AddressList);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment