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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement miles/kilometer selector #252

Merged
merged 11 commits into from
Oct 6, 2019
8 changes: 5 additions & 3 deletions App/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import {
ApiContextProvider,
ErrorContextProvider,
FrequencyContextProvider,
LocationContextProvider
LocationContextProvider,
DistanceUnitProvider
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
} from './stores';
import { setupAmplitude, track } from './util/amplitude';

Expand All @@ -46,7 +47,6 @@ export function App () {
const [ready, setReady] = useState(false);
useEffect(() => {
Promise.all([

Font.loadAsync({
'gotham-black': require('../assets/fonts/Gotham-Black.ttf'),
'gotham-book': require('../assets/fonts/Gotham-Book.ttf')
Expand Down Expand Up @@ -74,7 +74,9 @@ export function App () {
<LocationContextProvider>
<ApiContextProvider>
<FrequencyContextProvider>
<Screens />
<DistanceUnitProvider>
<Screens />
</DistanceUnitProvider>
</FrequencyContextProvider>
</ApiContextProvider>
</LocationContextProvider>
Expand Down
88 changes: 45 additions & 43 deletions App/Screens/About/About.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,7 @@

import Constants from 'expo-constants';
import React from 'react';
import {
Linking,
Platform,
ScrollView,
StyleSheet,
Text,
View
} from 'react-native';
import { Linking, Platform, ScrollView, StyleSheet, Switch, Text, View } from 'react-native';
import { ScrollIntoView, wrapScrollView } from 'react-native-scroll-into-view';
import { scale } from 'react-native-size-matters';
import { NavigationInjectedProps } from 'react-navigation';
Expand All @@ -33,6 +26,7 @@ import { BackButton } from '../../components';
import { i18n } from '../../localization';
import { trackScreen } from '../../util/amplitude';
import * as theme from '../../util/theme';
import { useDistanceUnit } from '../../stores/distanceUnit';
Copy link
Member

@amaury1093 amaury1093 Oct 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alphabetical by import location


const CustomScrollView = wrapScrollView(ScrollView);
const scrollViewOptions = {
Expand All @@ -57,9 +51,7 @@ const handleOpenAqi = () => {
};

const handleOpenArticle = () => {
Linking.openURL(
'http:https://berkeleyearth.org/air-pollution-and-cigarette-equivalence/'
);
Linking.openURL('http:https://berkeleyearth.org/air-pollution-and-cigarette-equivalence/');
};

const handleOpenGithub = () => {
Expand All @@ -77,35 +69,26 @@ interface AboutProps

export function About (props: AboutProps) {
const { navigation } = props;
const { distanceUnit, setDistanceUnit, localizedDistanceUnit } = useDistanceUnit();
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved

trackScreen('ABOUT');

const toggleDistanceSwitch = (value: boolean) => setDistanceUnit(value ? 'km' : 'mile');

return (
<CustomScrollView
scrollIntoViewOptions={scrollViewOptions}
style={theme.withPadding}
>
<BackButton
onPress={() => navigation.goBack()}
style={styles.backButton}
/>
<CustomScrollView scrollIntoViewOptions={scrollViewOptions} style={theme.withPadding}>
<BackButton onPress={() => navigation.goBack()} style={styles.backButton} />

<View style={styles.section}>
<Text style={styles.h2}>
{i18n.t('about_how_do_you_calculate_the_number_of_cigarettes_title')}
</Text>
<Text style={theme.text}>
{i18n.t(
'about_how_do_you_calculate_the_number_of_cigarettes_message_1'
)}{' '}
{i18n.t('about_how_do_you_calculate_the_number_of_cigarettes_message_1')}{' '}
<Text onPress={handleOpenArticle} style={theme.link}>
{i18n.t(
'about_how_do_you_calculate_the_number_of_cigarettes_link_1'
)}
{i18n.t('about_how_do_you_calculate_the_number_of_cigarettes_link_1')}
</Text>
{i18n.t(
'about_how_do_you_calculate_the_number_of_cigarettes_message_2'
)}
{i18n.t('about_how_do_you_calculate_the_number_of_cigarettes_message_2')}
<Text style={styles.micro}>&micro;</Text>
g/m&sup3;
{' \u207D'}
Expand All @@ -126,15 +109,11 @@ export function About (props: AboutProps) {
style={styles.section}
>
<Text style={styles.h2}>{i18n.t('about_beta_inaccurate_title')}</Text>
<Text style={theme.text}>
{i18n.t('about_beta_inaccurate_message')}
</Text>
<Text style={theme.text}>{i18n.t('about_beta_inaccurate_message')}</Text>
</ScrollIntoView>

<View style={styles.section}>
<Text style={styles.h2}>
{i18n.t('about_where_does_data_come_from_title')}
</Text>
<Text style={styles.h2}>{i18n.t('about_where_does_data_come_from_title')}</Text>
<Text style={theme.text}>
{i18n.t('about_where_does_data_come_from_message_1')}{' '}
<Text onPress={handleOpenAqi} style={theme.link}>
Expand All @@ -145,17 +124,11 @@ export function About (props: AboutProps) {
</View>

<ScrollIntoView
onMount={
navigation.getParam('scrollInto') === 'aboutWhyIsTheStationSoFarTitle'
}
onMount={navigation.getParam('scrollInto') === 'aboutWhyIsTheStationSoFarTitle'}
style={styles.section}
>
<Text style={styles.h2}>
{i18n.t('about_why_is_the_station_so_far_title')}
</Text>
<Text style={theme.text}>
{i18n.t('about_why_is_the_station_so_far_message')}
</Text>
<Text style={styles.h2}>{i18n.t('about_why_is_the_station_so_far_title')}</Text>
<Text style={theme.text}>{i18n.t('about_why_is_the_station_so_far_message')}</Text>
</ScrollIntoView>

<View style={styles.section}>
Expand All @@ -169,6 +142,18 @@ export function About (props: AboutProps) {
</Text>
</View>

<View style={styles.distance}>
<Text style={styles.h2}>{i18n.t('about_distance_unit_title')}</Text>
<View style={styles.distanceSwitchWrapper}>
<Switch
onValueChange={toggleDistanceSwitch}
value={distanceUnit === 'km'}
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
trackColor={{ true: theme.primaryColor, false: theme.iconBackgroundColor }}
/>
<Text style={styles.distanceText}>{localizedDistanceUnit('long')}</Text>
</View>
</View>

<View style={styles.credits}>
<Text style={styles.h2}>{i18n.t('about_credits_title')}</Text>
<Text style={theme.text}>
Expand Down Expand Up @@ -217,6 +202,23 @@ const styles = StyleSheet.create({
marginBottom: theme.spacing.normal,
paddingTop: theme.spacing.big
},
distance: {
borderTopColor: theme.iconBackgroundColor,
borderTopWidth: 1,
marginBottom: theme.spacing.big,
paddingTop: theme.spacing.big
},
distanceSwitchWrapper: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center'
},
distanceText: {
...theme.text,
fontSize: scale(14),
paddingLeft: theme.spacing.small,
textTransform: 'capitalize'
},
h2: {
...theme.title,
fontSize: scale(20),
Expand Down
27 changes: 7 additions & 20 deletions App/Screens/Details/Details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,8 @@ import { Header } from './Header';
import { i18n } from '../../localization';
import { ApiContext, CurrentLocationContext } from '../../stores';
import { trackScreen } from '../../util/amplitude';
import {
distanceToStation,
getCorrectLatLng,
DistanceUnit
} from '../../util/station';
import { distanceToStation, getCorrectLatLng } from '../../util/station';
import { useDistanceUnit } from '../../stores/distanceUnit';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alphabetical


interface DetailsProps extends NavigationInjectedProps {}

Expand All @@ -43,9 +40,8 @@ export function Details (props: DetailsProps) {

const [showMap, setShowMap] = useState(false);
const { api } = useContext(ApiContext);
const { currentLocation: _currentLocation } = useContext(
CurrentLocationContext
);
const { currentLocation: _currentLocation } = useContext(CurrentLocationContext);
const { distanceUnit } = useDistanceUnit();

trackScreen('DETAILS');

Expand All @@ -68,14 +64,7 @@ export function Details (props: DetailsProps) {
// object` error. It's related to the MapView below.
const currentLocation = { ..._currentLocation! };

const haversineDistanceUnit = i18n.t(
'haversine_distance_unit'
) as DistanceUnit;
const distance = distanceToStation(
currentLocation!,
api!,
haversineDistanceUnit
);
const distance = distanceToStation(currentLocation!, api!, distanceUnit);

const station = {
description: api!.shootISmoke.station || '',
Expand All @@ -94,11 +83,9 @@ export function Details (props: DetailsProps) {
<MapView
initialRegion={{
latitude: (currentLocation.latitude + station.latitude) / 2,
latitudeDelta:
Math.abs(currentLocation.latitude - station.latitude) * 2,
latitudeDelta: Math.abs(currentLocation.latitude - station.latitude) * 2,
longitude: (currentLocation.longitude + station.longitude) / 2,
longitudeDelta:
Math.abs(currentLocation.longitude - station.longitude) * 2
longitudeDelta: Math.abs(currentLocation.longitude - station.longitude) * 2
}}
onMapReady={handleMapReady}
style={styles.map}
Expand Down
4 changes: 3 additions & 1 deletion App/Screens/Details/Distance/Distance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ import { StyleSheet, Text } from 'react-native';
import { Banner } from '../../../components';
import { i18n } from '../../../localization';
import * as theme from '../../../util/theme';
import { useDistanceUnit } from '../../../stores/distanceUnit';

interface DistanceProps {
distance: number;
}

export function Distance (props: DistanceProps) {
const distanceUnit = i18n.t('distance_unit');
const { localizedDistanceUnit } = useDistanceUnit();
const distanceUnit = localizedDistanceUnit('short');

return (
<Banner elevated shadowPosition="top" style={styles.banner}>
Expand Down
36 changes: 9 additions & 27 deletions App/Screens/Home/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,15 @@
// along with Sh**t! I Smoke. If not, see <http:https://www.gnu.org/licenses/>.

import React, { useContext } from 'react';
import {
GestureResponderEvent,
Image,
StyleSheet,
Text,
View
} from 'react-native';
import { GestureResponderEvent, Image, StyleSheet, Text, View } from 'react-native';
import { scale } from 'react-native-size-matters';

import alert from '../../../../assets/images/alert.png';
import { ChangeLocation, CurrentLocation } from '../../../components';
import { i18n } from '../../../localization';
import { ApiContext, CurrentLocationContext } from '../../../stores';
import {
distanceToStation,
isStationTooFar,
DistanceUnit
} from '../../../util/station';
import { distanceToStation, isStationTooFar } from '../../../util/station';
import { useDistanceUnit } from '../../../stores/distanceUnit';
import * as theme from '../../../util/theme';

interface HeaderProps {
Expand All @@ -42,33 +33,24 @@ interface HeaderProps {
export function Header (props: HeaderProps) {
const { api } = useContext(ApiContext)!;
const { currentLocation, isGps } = useContext(CurrentLocationContext);
const { localizedDistanceUnit, distanceUnit } = useDistanceUnit();
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
const { onChangeLocationClick } = props;

const distanceUnit = i18n.t('distance_unit');
const haversineDistanceUnit = i18n.t(
'haversine_distance_unit'
) as DistanceUnit;
const distance = distanceToStation(
currentLocation!,
api!,
haversineDistanceUnit
);
const shortDistanceUnit = localizedDistanceUnit('short');
const distance = distanceToStation(currentLocation!, api!, distanceUnit);
console.log('distance', distance + distanceUnit);
amaury1093 marked this conversation as resolved.
Show resolved Hide resolved
const isTooFar = isStationTooFar(currentLocation!, api!);

return (
<View style={styles.container}>
<View style={styles.currentLocation}>
<CurrentLocation
api={api!}
currentLocation={currentLocation!}
numberOfLines={2}
/>
<CurrentLocation api={api!} currentLocation={currentLocation!} numberOfLines={2} />
<View style={styles.distance}>
{isTooFar && <Image source={alert} style={styles.warning} />}
<Text style={styles.distanceText}>
{i18n.t('home_header_air_quality_station_distance', {
distanceToStation: distance,
distanceUnit
distanceUnit: shortDistanceUnit
})}{' '}
{!isGps && i18n.t('home_header_from_search')}
</Text>
Expand Down
9 changes: 6 additions & 3 deletions App/localization/languages/en-us.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@
"details_header_latest_update_ago": "ago",
"details_header_primary_pollutant_label": "Primary Pollutant:",
"details_distance_label": "AQI Station: {{distanceToStation}}{{distanceUnit}} away",
"distance_unit": "mi",
"haversine_distance_unit": "mile",
"distance_unit_short_km": "km",
"distance_unit_short_mi": "mi",
"distance_unit_long_km": "kilometer",
"distance_unit_long_mi": "mile",
"past_stations_loading": "Loading",
"past_stations_date_from_to": "{{startDate}} to {{endDate}}",
"past_stations_monitored_weekly": "Stations monitored from you during the week",
Expand All @@ -76,6 +78,7 @@
"about_weird_results_message_1": "We have also encountered a few surprising results: large cities with better air than small villages; sudden huge increases in the number of cigarettes; stations of the same town showing significantly different numbers... The fact is air quality depends on several factors such as temperature, pressure, humidity and even wind direction and intensity. If the result seems weird for you, check",
"about_weird_results_link_1": "WAQI",
"about_weird_results_message_2": "for more information and history on your station.",
"about_distance_unit_title": "Distance Unit",
"about_credits_title": "Credits",
"about_credits_concept_and_development": "Concept & Development by",
"about_credits_design_and_copywriting": "Design & Copywriting by",
Expand All @@ -84,4 +87,4 @@
"about_credits_available_github": "available on Github",
"about_language": "Language",
"current_location_unknown_station": "Unknown AQI station"
}
}
9 changes: 6 additions & 3 deletions App/localization/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,10 @@
"details_header_latest_update_ago": "ago",
"details_header_primary_pollutant_label": "Primary Pollutant:",
"details_distance_label": "AQI Station: {{distanceToStation}}{{distanceUnit}} away",
"distance_unit": "km",
"haversine_distance_unit": "km",
"distance_unit_short_km": "km",
"distance_unit_short_mi": "mi",
"distance_unit_long_km": "kilometer",
"distance_unit_long_mi": "mile",
"past_stations_loading": "Loading",
"past_stations_date_from_to": "{{startDate}} to {{endDate}}",
"past_stations_monitored_weekly": "Stations monitored from you during the week",
Expand All @@ -76,6 +78,7 @@
"about_weird_results_message_1": "We have also encountered a few surprising results: large cities with better air than small villages; sudden huge increases in the number of cigarettes; stations of the same town showing significantly different numbers... The fact is air quality depends on several factors such as temperature, pressure, humidity and even wind direction and intensity. If the result seems weird for you, check",
"about_weird_results_link_1": "WAQI",
"about_weird_results_message_2": "for more information and history on your station.",
"about_distance_unit_title": "Distance Unit",
"about_credits_title": "Credits",
"about_credits_concept_and_development": "Concept & Development by",
"about_credits_design_and_copywriting": "Design & Copywriting by",
Expand All @@ -84,4 +87,4 @@
"about_credits_available_github": "available on Github",
"about_language": "Language",
"current_location_unknown_station": "Unknown AQI station"
}
}
Loading