diff --git a/app/Entry.js b/app/Entry.js index e2fd324286..6bd9f3e682 100644 --- a/app/Entry.js +++ b/app/Entry.js @@ -24,6 +24,7 @@ import AboutScreen from './views/About'; import ChooseProviderScreen from './views/ChooseProvider'; import { GetStoreData, SetStoreData } from './helpers/General'; +import { PARTICIPATE } from './constants/storage'; const Stack = createStackNavigator(); @@ -36,7 +37,7 @@ class Entry extends Component { } componentDidMount() { - GetStoreData('PARTICIPATE') + GetStoreData(PARTICIPATE) .then(isParticipating => { console.log(isParticipating); this.setState({ diff --git a/app/constants/authorities.js b/app/constants/authorities.js new file mode 100644 index 0000000000..11bd76193d --- /dev/null +++ b/app/constants/authorities.js @@ -0,0 +1,5 @@ +export const PUBLIC_DATA_URL = + 'https://raw.githubusercontent.com/beoutbreakprepared/nCoV2019/master/latest_data/latestdata.csv'; + +export const AUTHORITIES_LIST_URL = + 'https://raw.githubusercontent.com/tripleblindmarket/safe-places/develop/healthcare-authorities.yaml'; diff --git a/app/constants/storage.js b/app/constants/storage.js new file mode 100644 index 0000000000..64133b259b --- /dev/null +++ b/app/constants/storage.js @@ -0,0 +1,6 @@ +export const LOCATION_DATA = 'LOCATION_DATA'; +export const CONTACT_DATA = 'CONTACT_DATA'; +export const PARTICIPATE = 'PARTICIPATE'; +export const MY_UUIDs = 'MY_UUIDs'; +export const CROSSED_PATHS = 'CROSSED_PATHS'; +export const LANG_OVERRIDE = 'LANG_OVERRIDE'; diff --git a/app/helpers/GoogleData.js b/app/helpers/GoogleData.js index 8f907b4f78..99f99db934 100644 --- a/app/helpers/GoogleData.js +++ b/app/helpers/GoogleData.js @@ -2,6 +2,7 @@ * Import a Google JSon into the Database. */ import { GetStoreData, SetStoreData } from '../helpers/General'; +import { LOCATION_DATA } from '../constants/storage'; function BuildLocalFormat(placeVisit) { return (loc = { @@ -52,7 +53,7 @@ function Merge(localDataJSON, googleDataJSON) { } export async function MergeJSONWithLocalData(googleDataJSON) { - GetStoreData('LOCATION_DATA').then(locationArray => { + GetStoreData(LOCATION_DATA).then(locationArray => { let locationData; if (locationArray !== null) { @@ -64,6 +65,6 @@ export async function MergeJSONWithLocalData(googleDataJSON) { Merge(locationData, googleDataJSON); console.log('Saving on array'); - SetStoreData('LOCATION_DATA', locationData); + SetStoreData(LOCATION_DATA, locationData); }); } diff --git a/app/helpers/Intersect.js b/app/helpers/Intersect.js index 8d9f7f8d67..863f911c5e 100644 --- a/app/helpers/Intersect.js +++ b/app/helpers/Intersect.js @@ -5,9 +5,10 @@ */ import { GetStoreData, SetStoreData } from '../helpers/General'; +import { LOCATION_DATA, CROSSED_PATHS } from '../constants/storage'; export async function IntersectSet(concernLocationArray, completion) { - GetStoreData('LOCATION_DATA').then(locationArrayString => { + GetStoreData(LOCATION_DATA).then(locationArrayString => { var locationArray; if (locationArrayString !== null) { locationArray = JSON.parse(locationArrayString); @@ -95,7 +96,7 @@ export async function IntersectSet(concernLocationArray, completion) { // TODO: Show in the UI! console.log('Crossing results: ', dayBin); - SetStoreData('CROSSED_PATHS', dayBin); // TODO: Store per authority? + SetStoreData(CROSSED_PATHS, dayBin); // TODO: Store per authority? completion(dayBin); }); } diff --git a/app/helpers/authorities.js b/app/helpers/authorities.js new file mode 100644 index 0000000000..11bd76193d --- /dev/null +++ b/app/helpers/authorities.js @@ -0,0 +1,5 @@ +export const PUBLIC_DATA_URL = + 'https://raw.githubusercontent.com/beoutbreakprepared/nCoV2019/master/latest_data/latestdata.csv'; + +export const AUTHORITIES_LIST_URL = + 'https://raw.githubusercontent.com/tripleblindmarket/safe-places/develop/healthcare-authorities.yaml'; diff --git a/app/locales/languages.js b/app/locales/languages.js index 05abc327f9..5392728137 100644 --- a/app/locales/languages.js +++ b/app/locales/languages.js @@ -1,6 +1,7 @@ import i18next from 'i18next'; import { getLanguages } from 'react-native-i18n'; import { GetStoreData } from '../helpers/General'; +import { LANG_OVERRIDE } from '../constants/storage'; // Refer this for checking the codes and creating new folders https://developer.chrome.com/webstore/i18n @@ -25,7 +26,7 @@ export function findUserLang(callback) { userLang = languages[0].split('-')[0]; // ['en-US' will become 'en'] // If the user specified a language override, use it instead - GetStoreData('LANG_OVERRIDE').then(res => { + GetStoreData(LANG_OVERRIDE).then(res => { if (typeof res === 'string') { console.log('Found user language override:'); console.log(res); diff --git a/app/services/BroadcastingService.js b/app/services/BroadcastingService.js index 7c020e35ef..1aecdacadb 100644 --- a/app/services/BroadcastingService.js +++ b/app/services/BroadcastingService.js @@ -5,6 +5,7 @@ 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 { CONTACT_DATA, MY_UUIDs } from '../constants/storage'; var currentUUID = null; var onDeviceFound = null; @@ -52,7 +53,7 @@ function saveContact(contact) { // Persist this contact data in our local storage of time/uuid values //console.log('[Bluetooth]', nowStr(), currentUUID, 'New Device Found', contact['uuid']); if (isNewContact(contact)) { - GetStoreData('CONTACT_DATA', false).then(contactArray => { + GetStoreData(CONTACT_DATA, false).then(contactArray => { if (!contactArray) { contactArray = []; } @@ -78,7 +79,7 @@ function saveContact(contact) { curated.length, ); - SetStoreData('CONTACT_DATA', curated); + SetStoreData(CONTACT_DATA, curated); }); } } @@ -86,7 +87,7 @@ function saveContact(contact) { function saveMyUUID(me) { // Persist this contact data in our local storage of time/lat/lon values - GetStoreData('MY_UUIDs', false).then(myUUIDArray => { + GetStoreData(MY_UUIDs, false).then(myUUIDArray => { if (!myUUIDArray) { myUUIDArray = []; } @@ -113,12 +114,12 @@ function saveMyUUID(me) { ); curated.push(uuid_time); - SetStoreData('MY_UUIDs', curated); + SetStoreData(MY_UUIDs, curated); }); } function loadLastUUIDAndBroadcast() { - GetStoreData('MY_UUIDs', false).then(myUUIDArray => { + GetStoreData(MY_UUIDs, false).then(myUUIDArray => { if (!myUUIDArray) { console.log( '[Bluetooth]', diff --git a/app/services/LocationService.js b/app/services/LocationService.js index 8f9d1cfaeb..5fa76c08a4 100644 --- a/app/services/LocationService.js +++ b/app/services/LocationService.js @@ -6,6 +6,7 @@ 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 { LOCATION_DATA, PARTICIPATE } from '../constants/storage'; let isBackgroundGeolocationConfigured = false; @@ -17,12 +18,11 @@ export class LocationData { this.minLocationSaveInterval = Math.floor(this.locationInterval * 0.8); // Minimum time between location information saves. 60000*4 = 4 minutes // Maximum time that we will backfill for missing data - this.maxBackfillTime = 60000 * 60 * 8 // Time (in milliseconds). 60000 * 60 * 8 = 8 hours - + this.maxBackfillTime = 60000 * 60 * 8; // Time (in milliseconds). 60000 * 60 * 8 = 8 hours } getLocationData() { - return GetStoreData('LOCATION_DATA').then(locationArrayString => { + return GetStoreData(LOCATION_DATA).then(locationArrayString => { let locationArray = []; if (locationArrayString !== null) { locationArray = JSON.parse(locationArrayString); @@ -55,7 +55,6 @@ export class LocationData { saveLocation(location) { // Persist this location data in our local storage of time/lat/lon values this.getLocationData().then(locationArray => { - // Always work in UTC, not the local time in the locationData let unixtimeUTC = Math.floor(location['time']); let unixtimeUTC_28daysAgo = unixtimeUTC - 60 * 60 * 24 * 1000 * 28; @@ -81,7 +80,7 @@ export class LocationData { // Backfill the stationary points, if available // The assumption is that if we see a gap in the data, the - // best guess is that the person was in that location for + // best guess is that the person was in that location for // the entire time. This makes it easier for a health authority // person to have a set of locations over time, and they can manually // redact the time frames that aren't correct. @@ -93,7 +92,7 @@ export class LocationData { // To protect ourselves, we won't backfill more than the // maxBackfillTime let lastRecordedTime = lastLocationArray['time']; - if ((unixtimeUTC - lastRecordedTime) > this.maxBackfillTime) { + if (unixtimeUTC - lastRecordedTime > this.maxBackfillTime) { lastRecordedTime = unixtimeUTC - this.maxBackfillTime; } @@ -105,9 +104,9 @@ export class LocationData { let lat_lon_time = { latitude: lastLocationArray['latitude'], longitude: lastLocationArray['longitude'], - time: newTS + time: newTS, }; - console.log('[INFO] backfill location:',lat_lon_time); + console.log('[INFO] backfill location:', lat_lon_time); curated.push(lat_lon_time); } } @@ -117,12 +116,12 @@ export class LocationData { let lat_lon_time = { latitude: location['latitude'], longitude: location['longitude'], - time: unixtimeUTC + time: unixtimeUTC, }; curated.push(lat_lon_time); - console.log('[INFO] saved location:',lat_lon_time); + console.log('[INFO] saved location:', lat_lon_time); - SetStoreData('LOCATION_DATA', curated); + SetStoreData(LOCATION_DATA, curated); }); } } @@ -353,8 +352,9 @@ export default class LocationServices { }); BackgroundGeolocation.removeAllListeners(); BackgroundGeolocation.stop(); + isBackgroundGeolocationConfigured = false; - SetStoreData('PARTICIPATE', 'false').then(() => { + SetStoreData(PARTICIPATE, 'false').then(() => { // nav.navigate('LocationTrackingScreen', {}); }); } diff --git a/app/views/ChooseProvider.js b/app/views/ChooseProvider.js index 1b31409f11..de6c7d238f 100644 --- a/app/views/ChooseProvider.js +++ b/app/views/ChooseProvider.js @@ -32,9 +32,7 @@ import closeIcon from './../assets/images/closeIcon.png'; import saveIcon from './../assets/images/saveIcon.png'; import languages from '../locales/languages'; import NavigationBarWrapper from '../components/NavigationBarWrapper'; - -const authoritiesListURL = - 'https://raw.githubusercontent.com/tripleblindmarket/safe-places/develop/healthcare-authorities.yaml'; +import { AUTHORITIES_LIST_URL } from '../constants/authorities'; const width = Dimensions.get('window').width; @@ -88,7 +86,7 @@ class ChooseProviderScreen extends Component { // this is much more performant. fileCache: true, }) - .fetch('GET', authoritiesListURL, { + .fetch('GET', AUTHORITIES_LIST_URL, { //some headers .. }) .then(result => { diff --git a/app/views/Export.js b/app/views/Export.js index 721a795edf..2ec78f0d16 100644 --- a/app/views/Export.js +++ b/app/views/Export.js @@ -5,7 +5,6 @@ import { View, Text, Image, - Dimensions, TouchableOpacity, BackHandler, StatusBar, @@ -33,7 +32,6 @@ import { SvgXml } from 'react-native-svg'; import close from './../assets/svgs/close'; import exportIcon from './../assets/svgs/export'; -const width = Dimensions.get('window').width; const base64 = RNFetchBlob.base64; function ExportScreen(props) { diff --git a/app/views/LocationTracking.js b/app/views/LocationTracking.js index afb4db8bde..c339c9cbac 100644 --- a/app/views/LocationTracking.js +++ b/app/views/LocationTracking.js @@ -49,6 +49,7 @@ import StateNoContact from './../assets/svgs/stateNoContact'; import StateUnknown from './../assets/svgs/stateUnknown'; import SettingsGear from './../assets/svgs/settingsGear'; import fontFamily from '../constants/fonts'; +import { PARTICIPATE, CROSSED_PATHS } from '../constants/storage'; const StateEnum = { UNKNOWN: 0, @@ -131,7 +132,7 @@ class LocationTracking extends Component { // already set on 12h timer, but run when this screen opens too this.intersect_tick(); - GetStoreData('CROSSED_PATHS').then(dayBin => { + GetStoreData(CROSSED_PATHS).then(dayBin => { if (dayBin === null) { console.log("Can't find crossed paths"); this.setState({ currentState: StateEnum.NO_CONTACT }); @@ -146,7 +147,7 @@ class LocationTracking extends Component { componentDidMount() { AppState.addEventListener('change', this._handleAppStateChange); BackHandler.addEventListener('hardwareBackPress', this.handleBackPress); - GetStoreData('PARTICIPATE') + GetStoreData(PARTICIPATE) .then(isParticipating => { if (isParticipating === 'true') { this.setState({ @@ -294,8 +295,8 @@ class LocationTracking extends Component { } willParticipate = () => { - SetStoreData('PARTICIPATE', 'true').then(() => { - // Turn off bluetooth for v1 + SetStoreData(PARTICIPATE, 'true').then(() => { + // Turn of bluetooth for v1 //BroadcastingServices.start(); }); // Check and see if they actually authorized in the system dialog. diff --git a/app/views/MapLocation.js b/app/views/MapLocation.js index e39a38c214..f6aef6f7e4 100644 --- a/app/views/MapLocation.js +++ b/app/views/MapLocation.js @@ -3,7 +3,6 @@ import React, { Component } from 'react'; import { View, Text, - Dimensions, StyleSheet, ImageBackground, StatusBar, @@ -33,8 +32,6 @@ import { SvgXml } from 'react-native-svg'; import fontFamily from '../constants/fonts'; import LocationServices, { LocationData } from '../services/LocationService'; -const width = Dimensions.get('window').width; - const InitialRegion = { latitude: 35.692863, longitude: -98.090517, diff --git a/app/views/Notification.js b/app/views/Notification.js index 5cc559b6df..56aeb32765 100644 --- a/app/views/Notification.js +++ b/app/views/Notification.js @@ -27,6 +27,7 @@ import { } from 'victory-native'; import Colors from '../constants/colors'; import NavigationBarWrapper from '../components/NavigationBarWrapper'; +import { CROSSED_PATHS } from '../constants/storage'; const width = Dimensions.get('window').width; const height = Dimensions.get('window').height; @@ -84,7 +85,7 @@ class NotificationScreen extends Component { resetState() {} getInitialState = async () => { - GetStoreData('CROSSED_PATHS').then(dayBin => { + GetStoreData(CROSSED_PATHS).then(dayBin => { console.log(dayBin); /* DEBUGGING TOOL -- handy for creating faux data diff --git a/app/views/Overlap.js b/app/views/Overlap.js index 05f5fda331..d1374e78d9 100644 --- a/app/views/Overlap.js +++ b/app/views/Overlap.js @@ -26,6 +26,8 @@ import backArrow from '../assets/images/backArrow.png'; import languages from '../locales/languages'; import CustomCircle from '../helpers/customCircle'; import fontFamily from '../constants/fonts'; +import { PUBLIC_DATA_URL } from '../constants/authorities'; +import { LOCATION_DATA } from '../constants/storage'; const width = Dimensions.get('window').width; @@ -36,8 +38,6 @@ const base64 = RNFetchBlob.base64; // The dataset is now hosted on Github due to the high demand for it. The // first Google Doc holding data (https://docs.google.com/spreadsheets/d/1itaohdPiAeniCXNlntNztZ_oRvjh0HsGuJXUJWET008/edit#gid=0) // points to this souce but no longer holds the actual data. -const public_data = - 'https://raw.githubusercontent.com/beoutbreakprepared/nCoV2019/master/latest_data/latestdata.csv'; const show_button_text = languages.t('label.show_overlap'); const overlap_true_button_text = languages.t( 'label.overlap_found_button_label', @@ -93,7 +93,7 @@ function OverlapScreen() { } async function populateMarkers() { - GetStoreData('LOCATION_DATA').then(locationArrayString => { + GetStoreData(LOCATION_DATA).then(locationArrayString => { var locationArray = JSON.parse(locationArrayString); if (locationArray !== null) { var markers = []; @@ -125,7 +125,7 @@ function OverlapScreen() { async function getInitialState() { try { - GetStoreData('LOCATION_DATA').then(locationArrayString => { + GetStoreData(LOCATION_DATA).then(locationArrayString => { const locationArray = JSON.parse(locationArrayString); if (locationArray !== null) { const { latitude, longitude } = locationArray.slice(-1)[0]; @@ -168,7 +168,7 @@ function OverlapScreen() { // this is much more performant. fileCache: true, }) - .fetch('GET', public_data, {}) + .fetch('GET', PUBLIC_DATA_URL, {}) .then(res => { // the temp file path console.log('The file saved to ', res.path()); diff --git a/app/views/Settings.js b/app/views/Settings.js index f29b535b15..fbcc7d7bff 100644 --- a/app/views/Settings.js +++ b/app/views/Settings.js @@ -6,17 +6,13 @@ import { TouchableOpacity, ScrollView, BackHandler, - Dimensions, } from 'react-native'; // This is the definitive listing of registered Healthcare Authorities. To // register, just submit a PR against that list on Github. Users are also // free to type in a non-official authority. // -const authoritiesListURL = - 'https://raw.githubusercontent.com/tripleblindmarket/safe-places/develop/healthcare-authorities.yaml'; -const width = Dimensions.get('window').width; import languages from './../locales/languages'; import ButtonWrapper from '../components/ButtonWrapper'; import NavigationBarWrapper from '../components/NavigationBarWrapper'; diff --git a/app/views/onboarding/Onboarding1.js b/app/views/onboarding/Onboarding1.js index 24c24f4360..364b0082dc 100644 --- a/app/views/onboarding/Onboarding1.js +++ b/app/views/onboarding/Onboarding1.js @@ -15,6 +15,7 @@ import fontFamily from '../../constants/fonts'; import languages, { findUserLang } from './../../locales/languages'; import NativePicker from '../../components/NativePicker'; import { SetStoreData } from '../../helpers/General'; +import { LANG_OVERRIDE } from '../../constants/storage'; const width = Dimensions.get('window').width; @@ -73,7 +74,7 @@ class Onboarding extends Component { ); }); - SetStoreData('LANG_OVERRIDE', itemValue); + SetStoreData(LANG_OVERRIDE, itemValue); }} /> diff --git a/app/views/onboarding/Onboarding5.js b/app/views/onboarding/Onboarding5.js index fdcdb07824..cee92bd7a7 100644 --- a/app/views/onboarding/Onboarding5.js +++ b/app/views/onboarding/Onboarding5.js @@ -26,8 +26,10 @@ import { SetStoreData } from '../../helpers/General'; import { isPlatformiOS } from './../../Util'; import { SvgXml } from 'react-native-svg'; import fontFamily from '../../constants/fonts'; +import { PARTICIPATE } from '../../constants/storage'; const width = Dimensions.get('window').width; + const PermissionStatusEnum = { UNKNOWN: 0, GRANTED: 1, @@ -171,7 +173,7 @@ class Onboarding extends Component { } else if (!this.isNotificationChecked()) { this.requestNotification(); } else { - SetStoreData('PARTICIPATE', 'true'); // replaces "start" button + SetStoreData(PARTICIPATE, 'true'); // replaces "start" button this.props.navigation.replace('LocationTrackingScreen'); } }