This commit is contained in:
MrARM
2019-08-31 18:18:14 -05:00
commit 4a7df79202
20 changed files with 6315 additions and 0 deletions

4
.expo-shared/assets.json Normal file
View File

@@ -0,0 +1,4 @@
{
"f9155ac790fd02fadcdeca367b02581c04a353aa6d5aa84409a59f6804c87acd": true,
"89ed26367cdb9b771858e026f2eb95bfdb90e5ae943e716575327ec325f39c44": true
}

11
.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
node_modules/**/*
.expo/*
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/
web-report/

12
.idea/bird-bam.iml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="JSX" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/bird-bam.iml" filepath="$PROJECT_DIR$/.idea/bird-bam.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

299
.idea/workspace.xml generated Normal file
View File

@@ -0,0 +1,299 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="1582f386-ce79-4cb6-aea9-8e19c50fae98" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/../.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/.idea/bird-bam.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/Button.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/TextInput.js" afterDir="false" />
<change afterPath="$PROJECT_DIR$/UserInterface.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../.idea/beepboop.iml" beforeDir="false" afterPath="$PROJECT_DIR$/../.idea/beepboop.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/../.idea/workspace.xml" afterDir="false" />
</list>
<ignored path="$PROJECT_DIR$/.tmp/" />
<ignored path="$PROJECT_DIR$/temp/" />
<ignored path="$PROJECT_DIR$/tmp/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/App.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="42">
<caret line="2" column="20" selection-start-line="2" selection-start-column="20" selection-end-line="2" selection-end-column="20" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="15" column="33" selection-start-line="15" selection-start-column="33" selection-end-line="15" selection-end-column="33" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/TextInput.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="357">
<caret line="17" selection-start-line="17" selection-end-line="17" />
<folding>
<element signature="e#0#26#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/Button.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="105">
<caret line="5" column="20" selection-start-line="5" selection-start-column="20" selection-end-line="6" selection-end-column="22" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/app.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="273">
<caret line="13" column="26" selection-start-line="13" selection-start-column="26" selection-end-line="13" selection-end-column="26" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/UserInterface.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="238">
<caret line="214" column="44" selection-start-line="214" selection-start-column="44" selection-end-line="214" selection-end-column="44" />
<folding>
<element signature="e#20#46#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/assets/splash.png">
<provider selected="true" editor-type-id="images" />
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="JavaScript File" />
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/app.json" />
<option value="$PROJECT_DIR$/Button.js" />
<option value="$PROJECT_DIR$/TextInput.js" />
<option value="$PROJECT_DIR$/package.json" />
<option value="$PROJECT_DIR$/ui.js" />
<option value="$PROJECT_DIR$/App.js" />
<option value="$PROJECT_DIR$/UserInterface.js" />
</list>
</option>
</component>
<component name="ProjectConfigurationFiles">
<option name="files">
<list>
<option value="$PROJECT_DIR$/.idea/bird-bam.iml" />
<option value="$PROJECT_DIR$/.idea/vcs.xml" />
<option value="$PROJECT_DIR$/.idea/misc.xml" />
<option value="$PROJECT_DIR$/.idea/modules.xml" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="width" value="1280" />
<option name="height" value="696" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="Scope" />
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="bird-bam" type="b2602c69:ProjectViewProjectNode" />
<item name="bird-bam" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="bird-bam" type="b2602c69:ProjectViewProjectNode" />
<item name="bird-bam" type="462c0819:PsiDirectoryNode" />
<item name="assets" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
</panes>
</component>
<component name="PropertiesComponent">
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.detected.package.tslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.path.for.package.tslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="node.js.selected.package.tslint" value="(autodetect)" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="nodejs_package_manager_path" value="yarn" />
<property name="settings.editor.selected.configurable" value="preferences.pluginManager" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="$PROJECT_DIR$/assets" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager">
<configuration name="run" type="js.build_tools.npm" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="start" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="1582f386-ce79-4cb6-aea9-8e19c50fae98" name="Default Changelist" comment="" />
<created>1567277341123</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1567277341123</updated>
<workItem from="1567277342489" duration="9493000" />
</task>
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="9493000" />
</component>
<component name="ToolWindowManager">
<frame x="-1" y="-2" width="1922" height="1047" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="npm" side_tool="true" />
<window_info id="Favorites" side_tool="true" />
<window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.1651715" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info anchor="bottom" id="Docker" show_stripe_button="false" />
<window_info anchor="bottom" id="Version Control" />
<window_info anchor="bottom" id="Terminal" />
<window_info anchor="bottom" id="Event Log" sideWeight="0.50026387" side_tool="true" visible="true" weight="0.19977678" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info anchor="bottom" id="Run" order="2" sideWeight="0.49973616" visible="true" weight="0.19977678" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/assets/logo.png">
<provider selected="true" editor-type-id="images" />
</entry>
<entry file="file://$PROJECT_DIR$/assets/icon.png">
<provider selected="true" editor-type-id="images" />
</entry>
<entry file="file://$PROJECT_DIR$/assets/splash.png">
<provider selected="true" editor-type-id="images" />
</entry>
<entry file="file://$PROJECT_DIR$/Button.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="105">
<caret line="5" column="20" selection-start-line="5" selection-start-column="20" selection-end-line="6" selection-end-column="22" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/TextInput.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="357">
<caret line="17" selection-start-line="17" selection-end-line="17" />
<folding>
<element signature="e#0#26#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/package.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="315">
<caret line="15" column="33" selection-start-line="15" selection-start-column="33" selection-end-line="15" selection-end-column="33" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/app.json">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="273">
<caret line="13" column="26" selection-start-line="13" selection-start-column="26" selection-end-line="13" selection-end-column="26" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/App.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="42">
<caret line="2" column="20" selection-start-line="2" selection-start-column="20" selection-end-line="2" selection-end-column="20" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/UserInterface.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="238">
<caret line="214" column="44" selection-start-line="214" selection-start-column="44" selection-end-line="214" selection-end-column="44" />
<folding>
<element signature="e#20#46#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
</component>
</project>

1
.watchmanconfig Normal file
View File

@@ -0,0 +1 @@
{}

20
App.js Normal file
View File

@@ -0,0 +1,20 @@
import React from 'react';
import { StyleSheet, View } from 'react-native';
import UserInterface from './UserInterface';
export default function App() {
return (
<View style={styles.container}>
<UserInterface />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}
});

108
Button.js Normal file
View File

@@ -0,0 +1,108 @@
import React from 'react';
import {
StyleSheet,
View,
Text,
TouchableOpacity,
} from 'react-native';
export default class Button extends React.Component {
render() {
if (!this.props.visible) {
return false;
}
if (!this.props.label) {
return false;
}
if (!this.props.onClick) {
return false;
}
return (
<View style={styles.component}>
<View style={styles.layouts}>
<View style={styles.layout}>
<View style={styles.itemcontainer}>
<View style={styles.itemcontainerInner}>
<TouchableOpacity
style={styles.chocolate}
onPress={this.props.onClick}
>
<Text style={styles.item1TouchableOpacity}>
{this.props.label}
</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
component: {
width: '100%',
flexDirection: 'row',
paddingLeft: 7.5,
paddingRight: 7.5,
paddingTop: 7.5,
paddingBottom: 7.5,
},
layouts: {
flexDirection: 'row',
flexWrap: 'wrap',
},
layout: {
width: '100%',
height: 90,
},
itemcontainer: {
width: '100%',
height: '100%',
paddingTop: 7.5,
paddingBottom: 7.5,
paddingLeft: 7.5,
paddingRight: 7.5,
},
itemcontainerInner: {
width: '100%',
height: '100%',
position: 'relative',
alignItems: 'center',
justifyContent: 'center',
},
chocolate: {
backgroundColor: '#1194f6',
borderWidth: 0,
borderColor: '#eee',
borderStyle: 'solid',
borderRadius: 4,
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
overflow: 'hidden',
padding: 10,
},
buttonText: {
color: '#fff',
fontSize: 14,
textAlign: 'center',
width: '100%',
},
});

116
TextInput.js Normal file
View File

@@ -0,0 +1,116 @@
import React from 'react';
import {
StyleSheet,
View,
KeyboardAvoidingView,
TextInput,
} from 'react-native';
export default class PTextInput extends React.Component {
constructor(props) {
super(props);
this.state = {
data: ""
}
}
render() {
if (!this.props.visible) {
return false;
}
if (!this.props.placeholder){
return false;
}
if(!this.props.textChange){
return false;
}
return (
<KeyboardAvoidingView
style={styles.component}
behavior={'padding'}
>
<View style={styles.layouts}>
<View style={styles.layout}>
<View style={styles.itemcontainer}>
<View style={styles.itemcontainerInner}>
<View style={styles.chocolate}>
<TextInput
style={styles.TextInput}
placeholder={this.props.placeholder}
underlineColorAndroid={"transparent"}
placeholderTextColor={"#AFAFAF"}
onChangeText={(val) => {
this.setState({ data: val });
this.props.textChange(val);
}}
value={this.state.data}
/>
</View>
</View>
</View>
</View>
</View>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
component: {
width: '100%',
flexDirection: 'row',
paddingLeft: 7.5,
paddingRight: 7.5,
paddingTop: 7.5,
paddingBottom: 7.5,
},
layouts: {
flexDirection: 'row',
flexWrap: 'wrap',
},
layout: {
width: '100%',
height: 90,
},
itemcontainer: {
width: '100%',
height: '100%',
paddingTop: 7.5,
paddingBottom: 7.5,
paddingLeft: 7.5,
paddingRight: 7.5,
},
itemcontainerInner: {
width: '100%',
height: '100%',
position: 'relative',
alignItems: 'center',
justifyContent: 'center',
},
chocolate: {
width: '100%',
height: '100%',
justifyContent: 'center',
padding: 10,
overflow: 'hidden',
},
TextInput: {
color: '#181818',
fontSize: 14,
textAlign: 'left',
width: '100%',
},
});

381
UserInterface.js Normal file
View File

@@ -0,0 +1,381 @@
// Secrets
/*
Secrets
Inputs:
trackme - hit set token to set fixed location to dynamic
setrad:<feet> - hit scan button to set scan radius
*/
import React from 'react';
import { Alert, StyleSheet, AsyncStorage, Image, Text, View } from 'react-native';
import Button from './Button';
import PTextInput from './TextInput';
import Hero from 'react-native-hero';
export default class UserInterface extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "",
status: "Not logged in",
token: undefined,
radius: "10000.0",
location: {
"timestamp": 1533729980953.91,
"coords": {
"accuracy": 5,
"altitude": 0,
"altitudeAccuracy": -1,
"heading": -1,
"latitude": 39.03467555,
"longitude": -94.5804479,
"speed": -1
}
},
birdsobj: undefined
}
}
// Feet calculation
distance(lat1, lon1, lat2, lon2) {
if ((lat1 == lat2) && (lon1 == lon2)) {
return 0;
}
else {
var radlat1 = Math.PI * lat1/180;
var radlat2 = Math.PI * lat2/180;
var theta = lon1-lon2;
var radtheta = Math.PI * theta/180;
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
if (dist > 1) {
dist = 1;
}
dist = Math.acos(dist);
dist = dist * 180/Math.PI;
dist = dist * 60 * 1.1515;
dist = dist * 5280;
return dist;
}
}
// Generate headers to send to bird
genHeaders(token){
if(token === 'registration'){
return {
'app-version': '4.46.1.9',
'os-version': '6.0',
'user-agent': 'Android - 6.0',
'connection-type': '4G',
'device-model': 'Android SDK built for x86_64',
'battery-level': '0',
'device-name': 'generic_x86_64',
'carrier-name': 'Android',
'device-id': '5aeb9526b4a9b0ef',
'platform': 'android',
'location': '{"accuracy":11.0,"altitude":130.0,"heading":null,"latitude":39.03467555,"longitude":-94.5804479,"mocked":false,"speed":10.728463172912598}',
'bluetooth-state': 'disabled',
'app-name': 'bird',
'accept-language': 'en-US'
};
}
return {
'app-version': '4.46.1.9',
'os-version': '6.0',
'user-agent': 'Android - 6.0',
'connection-type': '4G',
'device-model': 'Android SDK built for x86_64',
'battery-level': '0',
'device-name': 'generic_x86_64',
'carrier-name': 'Android',
'device-id': '5aeb9526b4a9b0ef',
'platform': 'android',
'location': '{"accuracy":11.0,"altitude":130.0,"heading":null,"latitude":39.03467555,"longitude":-94.5804479,"mocked":false,"speed":10.728463172912598}',
'bluetooth-state': 'disabled',
'app-name': 'bird',
'authorization': 'Bird '+token,
'accept-language': 'en-US'
};
}
// Takes an email token and converts it to a usable session
register(){
// Secret tracking keyword
if(this.state.text.toLowerCase() === 'trackme'){
this.getLocation();
} else{
// Real function
if(this.state.text.length >24 && this.state.text.length <20){
Alert.alert('This is not a valid registration token');
} else{
// https://enyam4wrrj28.x.pipedream.net/request/accept
// https://api.birdapp.com/request/accept
fetch('https://api.birdapp.com/request/accept',{method: 'PUT', headers: {...this.genHeaders('registration'), 'content-type': 'application/json; charset=UTF-8'}, body: JSON.stringify({token: this.state.text})})
.then((response) => response.json())
.then( (output) => {
console.log(output);
if(typeof output.code === 'number'){
this.setState({
status: "token invalid"
});
} else{
AsyncStorage.setItem('token', output.token);
this.setState({
status: "Logged in! Tap to scan",
token: output.token
});
}
}).catch(function (error) {
console.log(error);
});
//
}
}
};
// Scanner to seek out the birds
scan(){
if(this.state.text.toLowerCase().includes('setrad:')){
const rad = this.state.text.toLowerCase().split(':')[1];
this.setState({
status: `Radius set to ${rad}`,
radius: rad,
text: ""
});
} else{
if(typeof this.state.token === 'undefined'){
Alert.alert('No valid token is available');
} else{
//console.log(`https://api.birdapp.com/bird/nearby?latitude=${this.state.location.coords.latitude.toString()}&longitude=${this.state.location.coords.longitude.toString()}&radius=${this.state.radius}`);
fetch(`https://api.birdapp.com/bird/nearby?latitude=${this.state.location.coords.latitude.toString()}&longitude=${this.state.location.coords.longitude.toString()}&radius=10000.0`
,{method:'GET', headers: this.genHeaders(this.state.token)})
.then((response) => response.json())
.then( (output) => {
//console.log(output);
if(typeof output.birds !== 'object'){
this.setState({
status: "token invalid",
token: undefined
});
} else{
if(this.state.radius !== '10000.0'){
let newobj = [];
let total = output.birds.length;
let inc = 0;
output.birds.forEach((bird)=>{
inc++;
const reach = this.distance(this.state.location.coords.latitude, this.state.location.coords.longitude, bird.location.latitude, bird.location.longitude);
if(reach < parseInt(this.state.radius)){
newobj.push(bird);
}
if(inc === total){
// Done
total = newobj.length.toString();
this.setState({
status: `Scanned! Total birds in scope: ${total}`,
birdsobj: newobj
});
}
});
} else{
// No distance changing
const total = output.birds.length.toString();
this.setState({
status: `Scanned! Total birds in scope: ${total}`,
birdsobj: output.birds
});
}
}
}).catch(function (error) {
console.log(error);
});
}
}
}
// The beep
beep(){
if(typeof this.state.birdsobj === 'undefined'){
Alert.alert('No birds in sight');
} else{
this.state.birdsobj.forEach((bird)=>{
fetch('https://api.birdapp.com/bird/chirp',
{method:'PUT', headers:{...this.genHeaders(this.state.token), 'content-type': 'application/json; charset=UTF-8'}, body: JSON.stringify({
"bird_id": bird.id,
"alarm": false
})})
.then((response) => response.json())
.then( (output) => {
console.log(output);
}).catch(function (error) {
console.log(error);
});
});
}
};
// The bad one
alarm(){
Alert.alert(
'WARNING',
'This will cause all birds to emit a long, and loud alert sound. Please confirm you are absolutely sure about doing this.',
[
{text: 'NO', onPress: () => console.warn('cancelled'), style: 'cancel'},
{text: 'YES', onPress: () => {
//
if(typeof this.state.birdsobj === 'undefined'){
Alert.alert('No birds in sight');
} else{
this.state.birdsobj.forEach((bird)=>{
fetch('https://api.birdapp.com/bird/chirp',
{method:'PUT', headers:{...this.genHeaders(this.state.token), 'content-type': 'application/json; charset=UTF-8'}, body: JSON.stringify({
"bird_id": bird.id,
"alarm": true
})});
});
}
}},
]
);
};
// Check if the token exists, and if so try signing in
async checkUserSignedIn(){
let context = this;
try {
let value = await AsyncStorage.getItem('token');
if (value != null){
// Check if token is a valid one
fetch(`https://api.birdapp.com/user`, {
method: 'GET',
headers: this.genHeaders(value)
})
.then((response) => response.json())
.then( (output) => {
if(typeof output.government === 'undefined'){
this.setState({
status: "Old token invalid"
});
} else{
this.setState({
status: "Logged in! Tap to scan",
token: value
});
}
}).catch(function (error) {
console.log(error);
});
return true;
}
else {
// do something else
return false;
}
} catch (error) {
// Error retrieving data
return false;
}
}
// Get the location to localize your actions
getLocation(){
navigator.geolocation.getCurrentPosition(
position => {
const location = JSON.stringify(position);
this.setState({ position });
Alert.alert('Position acquired!',
'Lat: '+position.coords.latitude.toString() + '\nLon: '+position.coords.longitude.toString());
},
error => Alert.alert(error.message),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
);
}
componentDidMount() {
this.checkUserSignedIn();
// this.checkUserSignedIn().then((result)=>{
// if(result){
// this.props.navigation.navigate('Menu', {})
// }
// });
}
render() {
return (
<View style={styles.container}>
<View
onPress={()=>{this.getLocation()}}
>
<Image
style={styles.stretch}
source={require('./assets/logo.png')}
/>
</View>
<PTextInput
visible={ true }
placeholder = {"Insert login token OR set range"}
textChange={(val) => this.setState({ text: val })}
/>
<Button
visible={ true }
label={"Update auth token"}
onClick={()=>{this.register()}}
/>
<Hero
key={0}
source={require('./assets/birds.jpg')}
renderOverlay={() => (
<View
style={{ padding: 40 }}
onPress={()=>{this.scan()}}
>
<Text
style={styles.input}
onPress={()=>{this.scan()}}
>{this.state.status}</Text>
</View>
)}
/>
<Button
visible={ true }
label={"Beep"}
onClick={()=>{this.beep()}}
/>
<Button
visible={ true }
label={"Alarm"}
onClick={()=>{this.alarm()}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
stretch: {
width: 75,
height: 75,
resizeMode: 'stretch'
},
input: {
fontSize: 25,
color: '#fff',
fontWeight: '600',
textAlign: 'center'
}
});

30
app.json Normal file
View File

@@ -0,0 +1,30 @@
{
"expo": {
"name": "Bird Ringer",
"slug": "bird-bam",
"privacy": "public",
"sdkVersion": "34.0.0",
"platforms": [
"ios",
"android",
"web"
],
"version": "1.0.0",
"orientation": "portrait",
"icon": "./assets/logo.png",
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"updates": {
"fallbackToCacheTimeout": 0
},
"assetBundlePatterns": [
"**/*"
],
"ios": {
"supportsTablet": true
}
}
}

BIN
assets/birds.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

BIN
assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
assets/splash.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

6
babel.config.js Normal file
View File

@@ -0,0 +1,6 @@
module.exports = function(api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
};
};

22
package.json Normal file
View File

@@ -0,0 +1,22 @@
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject"
},
"dependencies": {
"expo": "^34.0.1",
"react": "16.8.3",
"react-dom": "^16.8.6",
"react-native": "https://github.com/expo/react-native/archive/sdk-34.0.0.tar.gz",
"react-native-web": "^0.11.4",
"react-native-hero": "^0.3.1"
},
"devDependencies": {
"babel-preset-expo": "^6.0.0"
},
"private": true
}

5285
yarn.lock Normal file

File diff suppressed because it is too large Load Diff