Skip to content

Commit

Permalink
Merge branch 'develop' into ts-dev-setup-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tstirrat authored Apr 13, 2020
2 parents ae85fee + e3ca1f3 commit 48063d5
Show file tree
Hide file tree
Showing 39 changed files with 629 additions and 557 deletions.
3 changes: 2 additions & 1 deletion App.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
*/

import React, { useEffect } from 'react';
import SplashScreen from 'react-native-splash-screen';
import { MenuProvider } from 'react-native-popup-menu';
import SplashScreen from 'react-native-splash-screen';

import Entry from './app/Entry';

const App: () => React$Node = () => {
Expand Down
34 changes: 13 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# COVID Safe Paths <img align="left" src="./assets/ShieldKeyHold512x512.png" data-canonical-src="./assets/ShieldKeyHold512x512.png" width="40" height="40"/> ![Android and iOS build on MacOS](https://github.com/tripleblindmarket/covid-safe-paths/workflows/Android%20and%20iOS%20build%20on%20MacOS/badge.svg)

**applying the technology and philosophy of Private Kit to COVID**
**Applying the technology and philosophy of Private Kit to COVID**

Help us stop COVID-19.

Expand All @@ -24,7 +24,7 @@ Safe Paths logs your device’s location once every five minutes and stores 28 d

**Downloads for COVID Safe Paths:** _coming soon!_

**Downloads for COVID Safe Paths:** [Google Play](https://play.google.com/store/apps/details?id=edu.mit.privatekit) | [Apple Store](https://apps.apple.com/us/app/private-kit-prototype/id1501903733)
**Downloads for Private Kit (technology beta):** [Google Play](https://play.google.com/store/apps/details?id=edu.mit.privatekit) | [Apple Store](https://apps.apple.com/us/app/private-kit-prototype/id1501903733)

# Development Overview

Expand All @@ -36,37 +36,29 @@ Please refer to `docs/Private Kit Diagram.png` for a basic overview on the seque

## Developer Setup

Refer to and run the dev_setup.sh (Linux/MacOS) or dev_setup.bat (Windows) for needed tools.
Run the ```dev_setup.sh``` (Linux/MacOS) or ```dev_setup.bat``` (Windows) for needed tools. It is assumed that Android Studio and/or xcode (on macOS) is set up and configured correctly to run applications in the simulator. For Android Studio, the dev_setup script can help you, but you still may need to configure at least one android virtual device (avd) from within Android Studio first before you can run the app.

### iOS Configuration - First Time Setup

1. Move to `ios` directory and run `pod install`
2. If you have any trouble with packages not found, try `react-native link` from project directory.
3. Look at running commands below.

### Google Maps API Key
You will need to generate a Google API key in order for the mapping features to work correctly. Refer to this guide [guide](https://developers.google.com/maps/documentation/ios-sdk/get-api-key) in order to create the API key.
## Running

Once created you will need to add it to two different places in the project. One for Android and one for iOS.
```yarn``` must be installed for this project, as it does a better job installing dependendies across platforms. The dev_setup script above should have done that for you.

* Android - open `android/app/src/main/AndroidManifest.xml`and search for `com.google.android.geo.API_KEY`. Add your key to the `android:value` property.
* iOS - open `ios/SafePaths/AppDelegate.m` and search for `GMSServices provideAPIKey` and replace line with `[GMSServices provideAPIKey:@"YOUR_API_KEY"];`
### Install modules to the correct locations

## Running
1. ```yarn install``` (always do this after a new clone or checkout)
2. ```yarn install:pod``` (additional step for macOS if you want to do an iOS build)

Install modules:
```yarn install``` (note ```yarn``` does a better job at installing dependencies on macOS, and it's mandatory to install `Yarn` on the local machine to run this project)
### Run the app in a simulator

To run, do:
To run in the Android simulator (Windows, Linux, macOS):
```
npx react-native run-android
```
or
or (on macOS only)
```
npx react-native run-ios --simulator="iPhone 8 Plus"
npx react-native run-ios
```

NOTE: In some cases, the abovementioned procedure leads to the error `Failed to load bundle - Could not connect to development server`. In these cases, kill all other react-native processes and try it again.
NOTE: In some cases, these procedures can lead to the error `Failed to load bundle - Could not connect to development server`. In these cases, kill all other react-native processes and try it again.

## Contributing

Expand Down
26 changes: 12 additions & 14 deletions app/Entry.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import React, { Component } from 'react';

import { NavigationContainer } from '@react-navigation/native';
import {
createStackNavigator,
CardStyleInterpolators,
createStackNavigator,
} from '@react-navigation/stack';
import { SafeAreaView } from 'react-native';
import LocationTracking from './views/LocationTracking';
import NewsScreen from './views/News';
import React, { Component } from 'react';

import { PARTICIPATE } from './constants/storage';
import { GetStoreData } from './helpers/General';
import AboutScreen from './views/About';
import ChooseProviderScreen from './views/ChooseProvider';
import ExportScreen from './views/Export';
import ImportScreen from './views/Import';
import OverlapScreen from './views/Overlap';
import SettingsScreen from './views/Settings';
import LicencesScreen from './views/Licenses';
import NotificationScreen from './views/Notification';
import LocationTracking from './views/LocationTracking';
import MapLocation from './views/MapLocation';
import NewsScreen from './views/News';
import NotificationScreen from './views/Notification';
import Onboarding1 from './views/onboarding/Onboarding1';
import Onboarding2 from './views/onboarding/Onboarding2';
import Onboarding3 from './views/onboarding/Onboarding3';
import Onboarding4 from './views/onboarding/Onboarding4';
import Onboarding5 from './views/onboarding/Onboarding5';
import AboutScreen from './views/About';
import ChooseProviderScreen from './views/ChooseProvider';

import { GetStoreData, SetStoreData } from './helpers/General';
import { PARTICIPATE } from './constants/storage';
import OverlapScreen from './views/Overlap';
import SettingsScreen from './views/Settings';

const Stack = createStackNavigator();

Expand Down
2 changes: 1 addition & 1 deletion app/Util.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Platform } from 'react-native';
import Moment from 'moment';
import { Platform } from 'react-native';

export function isPlatformiOS() {
return Platform.OS === 'ios';
Expand Down
5 changes: 3 additions & 2 deletions app/components/Button.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import PropTypes from 'prop-types';
import * as React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
import colors from '../constants/colors';
import LinearGradient from 'react-native-linear-gradient';
import PropTypes from 'prop-types';

import colors from '../constants/colors';

class Button extends React.Component {
render() {
Expand Down
7 changes: 4 additions & 3 deletions app/components/ButtonWrapper.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from 'react';
import { StyleSheet, Dimensions, View } from 'react-native';
import Button from './Button';
import PropTypes from 'prop-types';
import * as React from 'react';
import { Dimensions, StyleSheet, View } from 'react-native';

import fontFamily from '../constants/fonts';
import Button from './Button';

const width = Dimensions.get('window').width;

Expand Down
15 changes: 6 additions & 9 deletions app/components/NativePicker.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { Component } from 'react';
import {
View,
Text,
TouchableOpacity,
TextInput,
TouchableWithoutFeedback,
Picker,
Modal,
Picker,
Platform,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native';

// Code for the language select dropdown, for nice native handling on both iOS and Android.
Expand All @@ -23,7 +23,6 @@ export default class NativePicker extends Component {
render() {
// iOS and Android Pickers behave differently, handled below
if (Platform.OS === 'android') {

const selectedItem = this.props.items.find(
i => i.value === this.props.value,
);
Expand All @@ -35,7 +34,6 @@ export default class NativePicker extends Component {
onPress={() => this.setState({ modalVisible: true })}>
<TextInput
style={[styles.touchableTrigger, styles.touchableText]}

editable={false}
placeholder='Select language'
onChangeText={searchString => {
Expand Down Expand Up @@ -168,5 +166,4 @@ const styles = StyleSheet.create({
textAlign: 'center',
textTransform: 'uppercase',
},

});
9 changes: 5 additions & 4 deletions app/components/NavigationBarWrapper.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import PropTypes from 'prop-types';
import * as React from 'react';
import {
SafeAreaView,
Expand All @@ -7,12 +8,12 @@ import {
TouchableOpacity,
View,
} from 'react-native';
import PropTypes from 'prop-types';
import { SvgXml } from 'react-native-svg';

import backArrow from './../assets/svgs/backArrow';
import fontFamily from '../constants/fonts';
import Colors from '../constants/colors';
import { isPlatformiOS } from './../Util';
import { SvgXml } from 'react-native-svg';
import Colors from '../constants/colors';
import fontFamily from '../constants/fonts';

class NavigationBarWrapper extends React.Component {
render() {
Expand Down
2 changes: 1 addition & 1 deletion app/helpers/GoogleData.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { LOCATION_DATA } from '../constants/storage';
/**
* Import a Google JSon into the Database.
*/
import { GetStoreData, SetStoreData } from '../helpers/General';
import { LOCATION_DATA } from '../constants/storage';

function BuildLocalFormat(placeVisit) {
return (loc = {
Expand Down
3 changes: 2 additions & 1 deletion app/helpers/GoogleTakeOutAutoImport.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* Checks the download folder, unzips and imports all data from Google TakeOut
*/
import { unzip, subscribe } from 'react-native-zip-archive';
import { subscribe, unzip } from 'react-native-zip-archive';

import { MergeJSONWithLocalData } from '../helpers/GoogleData';

// require the module
Expand Down
12 changes: 2 additions & 10 deletions app/helpers/Intersect.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* v1 - Unencrypted, simpleminded (minimal optimization).
*/

import { GetStoreData, SetStoreData } from '../helpers/General';
import { LOCATION_DATA, CROSSED_PATHS } from '../constants/storage';
import PushNotification from 'react-native-push-notification';

import { isPlatformiOS } from './../Util';
import { CROSSED_PATHS, LOCATION_DATA } from '../constants/storage';
import { GetStoreData, SetStoreData } from '../helpers/General';
import languages from '../locales/languages';

export async function IntersectSet(concernLocationArray, completion) {
Expand Down Expand Up @@ -57,18 +57,10 @@ export async function IntersectSet(concernLocationArray, completion) {
let concernArray = normalizeData(concernLocationArray);

let concernTimeWindow = 1000 * 60 * 60 * 2; // +/- 2 hours window
let concernDistWindow = 60; // distance of concern, in feet

// At 38 degrees North latitude:
let ftPerLat = 364000; // 1 deg lat equals 364,000 ft
let ftPerLon = 288200; // 1 deg of longitude equals 288,200 ft

let nowUTC = new Date().toISOString();
let timeNow = Date.parse(nowUTC);

// Save a little CPU, no need to do sqrt()
let concernDistWindowSq = concernDistWindow * concernDistWindow;

// Both locationArray and concernLocationArray should be in the
// format [ { "time": 123, "latitude": 12.34, "longitude": 34.56 }]

Expand Down
5 changes: 0 additions & 5 deletions app/helpers/authorities.js

This file was deleted.

1 change: 1 addition & 0 deletions app/helpers/convertPointsToString.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pluralize from 'pluralize';

import languages from './../locales/languages';

export function timeSincePoint(point) {
Expand Down
10 changes: 5 additions & 5 deletions app/locales/languages.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import i18next from 'i18next';
import { getLanguages } from 'react-native-i18n';
import { GetStoreData } from '../helpers/General';

import { LANG_OVERRIDE } from '../constants/storage';
import { GetStoreData } from '../helpers/General';
import en from './en.json';
import ht from './ht.json';
import it from './it.json';

// Refer this for checking the codes and creating new folders https://developer.chrome.com/webstore/i18n

Expand All @@ -14,10 +18,6 @@ import { LANG_OVERRIDE } from '../constants/storage';
// 5. REMOVE all empty translations. e.g. "key": "", this will allow fallback to the default: English
// 6. import xyIndex from `./xy.json` and add the language to the block at the bottom

import en from './en.json';
import ht from './ht.json';
import it from './it.json';

// This will fetch the user's language
// Set up as a function so first onboarding screen can also update
// ...from async language override setting
Expand Down
1 change: 1 addition & 0 deletions app/services/BackgroundTaskService.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import BackgroundFetch from 'react-native-background-fetch';

import { check_intersect } from '../helpers/Intersect';

const INTERSECT_INTERVAL = 60 * 12; // 12 Hours, the value is received in minutes
Expand Down
9 changes: 5 additions & 4 deletions app/services/BroadcastingService.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { GetStoreData, SetStoreData } from '../helpers/General';
import { Alert } from 'react-native';
import { NativeEventEmitter, NativeModules } from 'react-native';
import BackgroundTimer from 'react-native-background-timer';
import UUIDGenerator from 'react-native-uuid-generator';
import AndroidBLEAdvertiserModule from 'react-native-ble-advertiser';
import { NativeEventEmitter, NativeModules } from 'react-native';
import { isPlatformAndroid, nowStr } from '../Util';
import UUIDGenerator from 'react-native-uuid-generator';

import { CONTACT_DATA, MY_UUIDs } from '../constants/storage';
import { GetStoreData, SetStoreData } from '../helpers/General';
import { isPlatformAndroid, nowStr } from '../Util';

var currentUUID = null;
var onDeviceFound = null;
Expand Down
16 changes: 10 additions & 6 deletions app/services/LocationService.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { GetStoreData, SetStoreData } from '../helpers/General';
import BackgroundGeolocation from '@mauron85/react-native-background-geolocation';
import PushNotificationIOS from '@react-native-community/push-notification-ios';
import PushNotification from 'react-native-push-notification';
import { isPlatformAndroid } from '../Util';
import languages from '../locales/languages';
import { isLocationsNearby as areLocationsNearby } from '../helpers/Intersect';

import { LOCATION_DATA, PARTICIPATE } from '../constants/storage';
import { GetStoreData, SetStoreData } from '../helpers/General';
import { isLocationsNearby as areLocationsNearby } from '../helpers/Intersect';
import languages from '../locales/languages';
import { isPlatformAndroid } from '../Util';

let isBackgroundGeolocationConfigured = false;

Expand Down Expand Up @@ -79,7 +80,7 @@ export class LocationData {
}

// Backfill the stationary points, if available
// The assumption is that if we see a gap in the data, and the
// The assumption is that if we see a gap in the data, and the
// device hasn't moved significantly, then we can fill in the missing data
// with the current location. This makes it easier for a health authority
// person to have a set of locations over time, and they can manually
Expand All @@ -98,7 +99,10 @@ export class LocationData {
// Actually do the backfill if the current point is nearby the previous
// point and the time is within the maximum time to backfill.
let lastRecordedTime = lastLocationArray['time'];
if (areCurrentPreviousNearby && unixtimeUTC - lastRecordedTime < this.maxBackfillTime) {
if (
areCurrentPreviousNearby &&
unixtimeUTC - lastRecordedTime < this.maxBackfillTime
) {
for (
let newTS = lastRecordedTime + this.locationInterval;
newTS < unixtimeUTC - this.locationInterval;
Expand Down
12 changes: 6 additions & 6 deletions app/views/About.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import React, { Component } from 'react';
import { StyleSheet, View, Text, ScrollView, BackHandler } from 'react-native';
import { BackHandler, ScrollView, StyleSheet, Text, View } from 'react-native';
import { SvgXml } from 'react-native-svg';

import team from './../assets/svgs/team';
import fontFamily from './../constants/fonts';
import languages from './../locales/languages';
import { isPlatformiOS } from './../Util';
import Colors from '../constants/colors';
import fontFamily from './../constants/fonts';
import team from './../assets/svgs/team';
import NavigationBarWrapper from '../components/NavigationBarWrapper';
import { SvgXml } from 'react-native-svg';
import lock from '../assets/svgs/lock';
import NavigationBarWrapper from '../components/NavigationBarWrapper';
import Colors from '../constants/colors';

class AboutScreen extends Component {
constructor(props) {
Expand Down
Loading

0 comments on commit 48063d5

Please sign in to comment.