Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement new design #49

Merged
merged 41 commits into from
Nov 17, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f8b1918
Move About to Screen
amaury1093 Nov 15, 2018
43a619c
First batch of changes
amaury1093 Nov 16, 2018
cfa6fd4
Show details in details page
amaury1093 Nov 16, 2018
a47394d
Add banner on details
amaury1093 Nov 16, 2018
12058e2
Move Header inside Home
amaury1093 Nov 16, 2018
e0dc841
Use raw everywhere
amaury1093 Nov 16, 2018
5f46983
Add MST
amaury1093 Nov 16, 2018
9ff71df
Fix details page
amaury1093 Nov 16, 2018
0041874
Fix layout on homepage
amaury1093 Nov 16, 2018
b8810b0
Fix homepage
amaury1093 Nov 16, 2018
dbb158a
Fix About page
amaury1093 Nov 16, 2018
4d140d2
Add section in about
amaury1093 Nov 16, 2018
ecf62ab
Fix navigation transitions
amaury1093 Nov 16, 2018
51a8c6b
Fix shadows in Details
amaury1093 Nov 16, 2018
97481f0
Fix Search
amaury1093 Nov 16, 2018
98688d7
Use PureComponent everywhere
amaury1093 Nov 16, 2018
58389a9
Adjust cigarette position
amaury1093 Nov 16, 2018
b4a53e1
Fix scrolling on home
amaury1093 Nov 17, 2018
c54342d
Reorganize screens
amaury1093 Nov 17, 2018
72ddd59
Put error in mst
amaury1093 Nov 17, 2018
813ecf4
Fix button link
amaury1093 Nov 17, 2018
4f4d90a
Fix color
amaury1093 Nov 17, 2018
1766fe7
Small bugfixes
amaury1093 Nov 17, 2018
32776ed
Fix bug pollutants
amaury1093 Nov 17, 2018
035e881
Fix small bugs
amaury1093 Nov 17, 2018
d0f6526
Change meta info
amaury1093 Nov 17, 2018
6500c62
Update screenshots
amaury1093 Nov 17, 2018
fff94ff
Limit screenshot width
amaury1093 Nov 17, 2018
bc54c49
Fix limit width
amaury1093 Nov 17, 2018
fa06fed
Use img tag for screenshots
amaury1093 Nov 17, 2018
03072b0
Smaller images
amaury1093 Nov 17, 2018
cb27fbb
Images side by side
amaury1093 Nov 17, 2018
b1a1b97
Slightly bigger images
amaury1093 Nov 17, 2018
a6140c2
Bump version
amaury1093 Nov 17, 2018
59936ce
Fix lint
amaury1093 Nov 17, 2018
cf44b20
Add smoke video as separate component
amaury1093 Nov 17, 2018
e61502e
Fix header layout in details
amaury1093 Nov 17, 2018
401fb58
Add about text
amaury1093 Nov 17, 2018
5d3d51b
Add warning icons
amaury1093 Nov 17, 2018
9f2a907
Fix some designs
amaury1093 Nov 17, 2018
00252d2
Add font-awesome
amaury1093 Nov 17, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Reorganize screens
  • Loading branch information
amaury1093 committed Nov 17, 2018
commit c54342db0632aa31057d6788a0c9792b31c7b6c3
16 changes: 8 additions & 8 deletions App/Screens/ErrorScreen/ErrorScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import React, { Component } from 'react';
import { Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native';

import error from '../../../assets/images/error.png';
import { Footer } from '../../components/Footer';
import * as theme from '../../utils/theme';

export class ErrorScreen extends Component {
goToSearch = () => this.props.navigation.navigate('Search');

render() {
const { onChangeLocationClick } = this.props;
return (
<View style={styles.container}>
<View />
Expand All @@ -25,18 +25,18 @@ export class ErrorScreen extends Component {
load your cigarettes.
</Text>
</View>
<TouchableOpacity onPress={onChangeLocationClick}>
</View>

<View>
<TouchableOpacity onPress={this.goToSearch}>
<View style={styles.chooseOther}>
<Text style={theme.bigButtonText}>CHOOSE OTHER LOCATION</Text>
</View>
</TouchableOpacity>
</View>
<View>
<Text style={styles.errorDescription}>
There's either a problem with our databases, or you don't have any
Air Monitoring Stations near you. Try again later!
</Text>
<Footer text="Click to know how the app works." />
</View>
</View>
);
Expand All @@ -46,14 +46,14 @@ export class ErrorScreen extends Component {
const styles = StyleSheet.create({
chooseOther: {
...theme.bigButton,
marginTop: theme.defaultSpacing
marginVertical: theme.defaultSpacing
},
container: {
...theme.fullScreen,
...theme.withPadding,
flexGrow: 1,
flexDirection: 'column',
justifyContent: 'space-between'
justifyContent: 'space-around'
},
errorDescription: {
...theme.text,
Expand Down
83 changes: 78 additions & 5 deletions App/Screens/Loading/Loading.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,32 @@
// Copyright (c) 2018, Amaury Martiny and the Shoot! I Smoke contributors
// SPDX-License-Identifier: GPL-3.0

import React, { PureComponent } from 'react';
import React, { Component } from 'react';
import { inject, observer } from 'mobx-react';
import { Location, Permissions } from 'expo';
import retry from 'async-retry';
import { StyleSheet, Text } from 'react-native';

import { Background } from './Background';
import * as dataSources from '../../utils/dataSources';
import * as theme from '../../utils/theme';

export class Loading extends PureComponent {
@inject('stores')
@observer
export class Loading extends Component {
state = {
longWaiting: false // If api is taking a long time
};

longWaitingTimeout = null; // The variable returned by setTimeout for longWaiting

componentWillReceiveProps({ gps }) {
if (!this.props.gps && gps) {
componentDidMount() {
this.fetchData();
}

componentDidUpdate(prevProps) {
if (!prevProps.stores.gps && this.props.gps) {
// Start a 2s timeout to occupy user while he's waiting.
this.longWaitingTimeout = setTimeout(
() => this.setState({ longWaiting: true }),
2000 // Set longWaiting after 2s of waiting
Expand All @@ -29,6 +40,63 @@ export class Loading extends PureComponent {
}
}

async fetchData() {
const { stores } = this.props;
const { location } = stores;
const { gps } = stores; // eslint-disable-line Only used to track mobx variable

try {
// The current { latitude, longitude } the user chose
let currentPosition = location.current;

this.setState({ error: null });

// If the currentLocation has been set by the user, then we don't refetch
// the user's GPS
if (!currentPosition) {
const { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
throw new Error('Permission to access location was denied.');
}

// const { coords } = await Location.getCurrentPositionAsync({});
// Uncomment to get random location
// coords = {
// latitude: Math.random() * 90,
// longitude: Math.random() * 90
// };
coords = {
latitude: 48.4,
longitude: 2.34
};

currentPosition = coords;

location.setCurrent(coords);
location.setGps(coords);
}

// We currently have 2 sources, aqicn, and windWaqi
// We put them in an array
const sources = [dataSources.aqicn, dataSources.windWaqi];

const _api = await retry(
async (_, attempt) => {
// Attempt starts at 1
const result = await sources[(attempt - 1) % 2](currentPosition);
return result;
},
{ retries: 3 } // 2 attemps per source
);

stores.setApi(_api);
} catch (error) {
// TODO Add to sentry
console.error(error);
throw error;
}
}

render() {
return (
<Background style={styles.container}>
Expand All @@ -45,7 +113,12 @@ export class Loading extends PureComponent {
);

renderText = () => {
const { gps } = this.props;
const {
stores: {
api, // eslint-disable-line Only used to subscribe to the mobx variable
location: { gps }
}
} = this.props;
const { longWaiting } = this.state;
let coughs = 0; // Number of times to show "Cough..."
if (gps) ++coughs;
Expand Down
114 changes: 29 additions & 85 deletions App/Screens/Screens.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import React, { Component } from 'react';
import { Dimensions, StyleSheet, View } from 'react-native';
import { inject, observer } from 'mobx-react';
import { Location, Permissions, Video } from 'expo';
import retry from 'async-retry';
import { Video } from 'expo';
import { createStackNavigator } from 'react-navigation';

import { About } from './About';
import * as dataSources from '../utils/dataSources';
import { Details } from './Details';
import { ErrorScreen } from './ErrorScreen';
import { Home } from './Home';
Expand All @@ -18,6 +16,20 @@ import { Search } from './Search';
import smokeVideo from '../../assets/video/smoke.mp4';
import * as theme from '../utils/theme';

const stackNavigatorOptions = initialRouteName => ({
cardStyle: {
backgroundColor: theme.backgroundColor
},
headerMode: 'none',
initialRouteName,
navigationOptions: {
headerVisible: false
}
});

/**
* The main stack navigator, for the app.
*/
const RootStack = createStackNavigator(
{
About: {
Expand All @@ -26,26 +38,29 @@ const RootStack = createStackNavigator(
Details: {
screen: Details
},
Error: {
screen: ErrorScreen
},
Home: {
screen: Home
},
Search: {
screen: Search
}
},
stackNavigatorOptions('Home')
);

/**
* A second stack navigator, for the error case.
*/
const ErrorStack = createStackNavigator(
{
cardStyle: {
backgroundColor: theme.backgroundColor
Error: {
screen: ErrorScreen
},
headerMode: 'none',
initialRouteName: 'Home',
navigationOptions: {
headerVisible: false
Search: {
screen: Search
}
}
},
stackNavigatorOptions('Error')
);

@inject('stores')
Expand All @@ -56,76 +71,10 @@ export class Screens extends Component {
showVideo: true // Showing video or not
};

componentDidMount() {
this.fetchData();
}

componentDidCatch(error) {
this.setState({ error });
}

componentDidUpdate(prevProps) {
if (!!prevProps.stores.api && !this.props.stores.api) {
this.fetchData();
}
}

async fetchData() {
const { stores } = this.props;
const { location } = stores;

try {
// The current { latitude, longitude } the user chose
let currentPosition = location.current;

this.setState({ error: null });

// If the currentLocation has been set by the user, then we don't refetch
// the user's GPS
if (!currentPosition) {
const { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
throw new Error('Permission to access location was denied.');
}

// const { coords } = await Location.getCurrentPositionAsync({});
// Uncomment to get random location
// coords = {
// latitude: Math.random() * 90,
// longitude: Math.random() * 90
// };
coords = {
latitude: 48.4,
longitude: 2.34
};

currentPosition = coords;

location.setCurrent(coords);
location.setGps(coords);
}

// We currently have 2 sources, aqicn, and windWaqi
// We put them in an array
const sources = [dataSources.aqicn, dataSources.windWaqi];

const _api = await retry(
async (_, attempt) => {
// Attempt starts at 1
const result = await sources[(attempt - 1) % 2](currentPosition);
return result;
},
{ retries: 3 } // 2 attemps per source
);

stores.setApi(_api);
} catch (error) {
// TODO Add to sentry
console.error(error);
this.setState({ error });
}
}

getVideoStyle = () => {
const {
stores: { cigarettes }
Expand Down Expand Up @@ -154,12 +103,7 @@ export class Screens extends Component {
const { error, showVideo } = this.state;

if (error) {
return (
<ErrorScreen
gps={location.gps}
onChangeLocationClick={this.handleSearchShow}
/>
);
return <ErrorStack />;
}

if (!api || !location.gps) {
Expand Down
4 changes: 2 additions & 2 deletions App/stores/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ export const ApiStore = types.maybe(
attributions: types.array(
types.model({
name: types.string,
url: types.string
url: types.maybe(types.string)
})
),
city: types.model({
geo: types.array(types.number),
name: types.string,
url: types.string
url: types.maybe(types.string)
}),
dominentpol: types.string,
iaqi: types.map(
Expand Down
2 changes: 1 addition & 1 deletion App/utils/dataSources/aqicn.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Constants } from 'expo';
*/
export const aqicn = async ({ latitude, longitude }) => {
const { data: response } = await axios.get(
`http:https://api.waqi.info/feed/geo:${latitude};${longitude}/?token=${
`http:https://api.wraqi.info/feed/geo:${latitude};${longitude}/?token=${
Constants.manifest.extra.waqiToken
}`,
{ timeout: 6000 }
Expand Down
10 changes: 5 additions & 5 deletions App/utils/dataSources/windWaqi.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import axios from 'axios';
*/
export const windWaqi = async ({ latitude, longitude }) => {
const { data: response } = await axios.get(
`https://wind.waqi.info/mapq/nearest?geo=1/${latitude}/${longitude}`,
`https://wind.waqi.inrfo/mapq/nearest?geo=1/${latitude}/${longitude}`,
{ timeout: 6000 }
);

Expand Down Expand Up @@ -42,17 +42,17 @@ export const windWaqi = async ({ latitude, longitude }) => {
}

return {
aqi: data.v,
aqi: +data.v,
attributions: [],
city: { geo: [+data.geo[0], +data.geo[1]], name: data.nlo },
dominentpol: data.pol,
iaqi: {
[data.pol]: {
v: data.v
v: +data.v
}
},
idx: data.x,
rawPm25: data.v, // TODO Find the real raw value https://github.com/amaurymartiny/shoot-i-smoke/issues/46
idx: +data.x,
rawPm25: +data.v, // TODO Find the real raw value https://github.com/amaurymartiny/shoot-i-smoke/issues/46
time: {
v: data.t
}
Expand Down