Skip to content

Commit

Permalink
Import LunchSpotApp code from messy livecoded repository
Browse files Browse the repository at this point in the history
  • Loading branch information
Swizec committed Mar 7, 2017
1 parent b278367 commit 1ec303c
Show file tree
Hide file tree
Showing 23 changed files with 354 additions and 65 deletions.
4 changes: 3 additions & 1 deletion LunchSpotApp/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,11 @@ android {
}

dependencies {
compile project(':react-native-maps')
compile project(':react-native-photo-view')
compile project(':react-native-share')
compile project(':react-native-linear-gradient')
compile project(':react-native-vector-icons')
compile project(':react-native-maps')
compile fileTree(dir: "libs", include: ["*.jar"])
compile "com.android.support:appcompat-v7:23.0.1"
compile "com.facebook.react:react-native:+" // From node_modules
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import android.app.Application;

import com.facebook.react.ReactApplication;
import com.airbnb.android.react.maps.MapsPackage;
import com.reactnative.photoview.PhotoViewPackage;
import cl.json.RNSharePackage;
import com.BV.LinearGradient.LinearGradientPackage;
import com.oblador.vectoricons.VectorIconsPackage;
import com.airbnb.android.react.maps.MapsPackage;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
Expand All @@ -26,9 +28,11 @@ public boolean getUseDeveloperSupport() {
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new MapsPackage(),
new PhotoViewPackage(),
new RNSharePackage(),
new LinearGradientPackage(),
new VectorIconsPackage(),
new MapsPackage()
new VectorIconsPackage()
);
}
};
Expand Down
8 changes: 6 additions & 2 deletions LunchSpotApp/android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
rootProject.name = 'LunchSpotApp'
include ':react-native-maps'
project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android')
include ':react-native-photo-view'
project(':react-native-photo-view').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-photo-view/android')
include ':react-native-share'
project(':react-native-share').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share/android')
include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':react-native-vector-icons'
project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android')
include ':react-native-maps'
project(':react-native-maps').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-maps/android')

include ':app'
127 changes: 127 additions & 0 deletions LunchSpotApp/components/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@

import React, { Component } from 'react';

import { Screen, Spinner, Examples } from '@shoutem/ui';
import { stringify as queryString } from 'query-string';

import styles from './styles';
import RecommendationsMap from './RecommendationsMap';
import { OverlayTopics, BottomTopics } from './Topics';

const CLIENT_ID = '4VMVDF0DJLP4DKSFNW210VFMEL1OJ3P5HAAQJGOC4YFYIOJ2';
const CLIENT_SECRET = 'ZXA5FEE4GJY4S525PBWUDM22R3FTNTOHKQ0FMJNV0GGBTYBU';
const FOURSQUARE_ENDPOINT = 'https://api.foursquare.com/v2/venues/explore';
const API_DEBOUNCE_TIME = 2000;

class App extends Component {
state = {
mapRegion: null,
gpsAccuracy: null,
recommendations: [],
lookingFor: null,
headerLocation: null,
last4sqCall: null
}
watchID = null

componentWillMount() {
this.watchID = navigator.geolocation.watchPosition((position) => {
let region = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
latitudeDelta: 0.00922*1.5,
longitudeDelta: 0.00421*1.5
}

this.onRegionChange(region, position.coords.accuracy);
});
}

componentWillUnmount() {
navigator.geolocation.clearWatch(this.watchID);
}

onRegionChange(region, gpsAccuracy) {
this.fetchVenues(region);

this.setState({
mapRegion: region,
gpsAccuracy: gpsAccuracy || this.state.gpsAccuracy
});
}

fetchVenues(region, lookingFor) {
if (!this.shouldFetchVenues(lookingFor)) return;

const query = this.venuesQuery(region, lookingFor);

fetch(`${FOURSQUARE_ENDPOINT}?${query}`)
.then(fetch.throwErrors)
.then(res => res.json())
.then(json => {
if (json.response.groups) {
this.setState({
recommendations: json.response.groups.reduce(
(all, g) => all.concat(g ? g.items : []), []
),
headerLocation: json.response.headerLocation,
last4sqCall: new Date()
});
}
})
.catch(err => console.log(err));
}

shouldFetchVenues(lookingFor) {
return lookingFor != this.state.lookingFor
|| this.state.last4sqCall === null
|| new Date() - this.state.last4sqCall > API_DEBOUNCE_TIME;
}

venuesQuery({ latitude, longitude }, lookingFor) {
return queryString({
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
v: 20170305,
ll: `${latitude}, ${longitude}`,
llAcc: this.state.gpsAccuracy,
section: lookingFor || this.state.lookingFor || 'food',
limit: 10,
openNow: 1,
venuePhotos: 1
});
}

onTopicSelect(lookingFor) {
this.fetchVenues(this.state.mapRegion, lookingFor);

this.setState({
lookingFor: lookingFor
});
}

render() {
const { mapRegion, lookingFor } = this.state;

if (mapRegion) {
return (
<Screen>
<RecommendationsMap {...this.state} onRegionChange={this.onRegionChange.bind(this)} />

{!lookingFor ? <OverlayTopics onTopicSelect={this.onTopicSelect.bind(this)} />
: <BottomTopics onTopicSelect={this.onTopicSelect.bind(this)} />}
</Screen>
);
}else{
return (
<Screen style={styles.centered}>
<Spinner styleName="large" />
</Screen>
);
}
}
}



export default App;
37 changes: 37 additions & 0 deletions LunchSpotApp/components/Recommendation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

import React, { Component } from 'react';

import MapView from 'react-native-maps';
import { Card, Image, View, Subtitle, Text, Caption } from '@shoutem/ui';


class Recommendation extends Component {
get photo() {
const photo = this.props.venue.photos.groups[0].items[0];

return `${photo.prefix}300x500${photo.suffix}`;
}

render() {
const { venue, tips } = this.props;

return (
<MapView.Marker coordinate={{latitude: venue.location.lat,
longitude: venue.location.lng}}>

<MapView.Callout>
<Card>
<Image styleName="medium-wide"
source={{uri: this.photo}} />
<View styleName="content">
<Subtitle>{venue.name}</Subtitle>
<Caption>{tips ? tips[0].text : ''}</Caption>
</View>
</Card>
</MapView.Callout>
</MapView.Marker>
)
}
}

export default Recommendation;
40 changes: 40 additions & 0 deletions LunchSpotApp/components/RecommendationsMap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

import React, { Component } from 'react';

import MapView from 'react-native-maps'
import { Subtitle, Title } from '@shoutem/ui';

import styles from './styles';
import Recommendation from './Recommendation';

const RecommendationsMap = ({ mapRegion, gpsAccuracy, recommendations, lookingFor,
headerLocation, onRegionChange }) => (

<MapView.Animated region={mapRegion}
style={styles.fullscreen}
onRegionChange={onRegionChange}>

<Title styleName="h-center multiline" style={styles.mapHeader}>
{lookingFor ? `${lookingFor} in` : ''} {headerLocation}
</Title>

<MapView.Circle center={mapRegion}
radius={gpsAccuracy*1.5}
strokeWidth={0.5}
strokeColor="rgba(66, 180, 230, 1)"
fillColor="rgba(66, 180, 230, 0.2)"
/>

<MapView.Circle center={mapRegion}
radius={5}
strokeWidth={0.5}
strokeColor="rgba(66, 180, 230, 1)"
fillColor="rgba(66, 180, 230, 1)"
/>

{recommendations.map(r => <Recommendation {...r} key={r.venue.id} />)}

</MapView.Animated>
);

export default RecommendationsMap;
30 changes: 30 additions & 0 deletions LunchSpotApp/components/Topics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@

import React, { Component } from 'react';
import { View, Button, Text, Overlay, Heading } from '@shoutem/ui';

import styles from './styles';

const TOPICS = ['food', 'drinks', 'coffee', 'shops', 'sights', 'arts'];

const OverlayTopics = ({ onTopicSelect }) => (
<Overlay styleName="fill-parent">
<Heading style={{marginBottom: 15}}>What do you feel like?</Heading>
{TOPICS.map(topic => (
<Button onPress={() => onTopicSelect(topic)} key={topic} style={{marginBottom: 10}}>
<Text>{topic}</Text>
</Button>
))}
</Overlay>
);

const BottomTopics = ({ onTopicSelect }) => (
<View styleName="horizontal">
{TOPICS.map(topic => (
<Button onPress={() => onTopicSelect(topic)} key={topic} styleName="muted">
<Text>{topic}</Text>
</Button>
))}
</View>
);

export { OverlayTopics, BottomTopics };
18 changes: 18 additions & 0 deletions LunchSpotApp/components/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

import { StyleSheet } from 'react-native';

const styles = {
fullscreen: {
flex: 1,
},
centered: {
justifyContent: 'center',
alignItems: 'center'
},
mapHeader: {
backgroundColor: "rgba(255, 255, 255, .7)",
paddingTop: 20
}
};

export default styles;
41 changes: 6 additions & 35 deletions LunchSpotApp/index.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,13 @@ import {
View
} from 'react-native';

import App from './components/App';
import { Examples } from '@shoutem/ui';

export default class LunchSpotApp extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit index.ios.js
</Text>
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
);
}
render() {
return (<App />);
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});

AppRegistry.registerComponent('LunchSpotApp', () => LunchSpotApp);
Loading

0 comments on commit 1ec303c

Please sign in to comment.