From 2a59365e57ec4a766210079d52e5f50bc7319e65 Mon Sep 17 00:00:00 2001 From: Steve Penrod Date: Sat, 11 Apr 2020 03:52:48 -0500 Subject: [PATCH 1/9] Add a debug mode for intersections Added the ability to enter a "debug" mode where an artificial intersection is created. This happens by: * Going to the About screen * Tapping on the Team icon 4 times * You can also return and tap 4 more times to toggle. When in this debug mode, faux intersection data is placed in the crossing arrays. This will either clear automatically during the 12-hour calculation, or can be cleared by the tester by returning to the About box and repeating the 4-tap. --- app/constants/storage.js | 1 + app/views/About.js | 65 +++++++++++++++++++++++++++++++---- app/views/LocationTracking.js | 29 +++++++++------- app/views/Notification.js | 12 +------ 4 files changed, 77 insertions(+), 30 deletions(-) diff --git a/app/constants/storage.js b/app/constants/storage.js index 64133b259b..f9bd4d8439 100644 --- a/app/constants/storage.js +++ b/app/constants/storage.js @@ -4,3 +4,4 @@ export const PARTICIPATE = 'PARTICIPATE'; export const MY_UUIDs = 'MY_UUIDs'; export const CROSSED_PATHS = 'CROSSED_PATHS'; export const LANG_OVERRIDE = 'LANG_OVERRIDE'; +export const DEBUG_MODE = 'DEBUG_MODE'; diff --git a/app/views/About.js b/app/views/About.js index 538de9ff64..57c12a6deb 100644 --- a/app/views/About.js +++ b/app/views/About.js @@ -9,12 +9,14 @@ import team from './../assets/svgs/team'; import NavigationBarWrapper from '../components/NavigationBarWrapper'; import { SvgXml } from 'react-native-svg'; import lock from '../assets/svgs/lock'; +import { GetStoreData, SetStoreData } from '../helpers/General'; +import { DEBUG_MODE, CROSSED_PATHS } from '../constants/storage'; class AboutScreen extends Component { constructor(props) { super(props); this.state = { - // + tapCount: 0, // tracks number of taps, for debugging }; } @@ -23,11 +25,18 @@ class AboutScreen extends Component { } handleBackPress = () => { + this.setState({ tapCount: 0 }); this.backToMain(); return true; }; componentDidMount() { + GetStoreData(DEBUG_MODE).then(dbgMode => { + if (dbgMode == 'true') { + this.setState({ tapCount: 4 }); + } + }); + BackHandler.addEventListener('hardwareBackPress', this.handleBackPress); } @@ -35,6 +44,41 @@ class AboutScreen extends Component { BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress); } + handleTapTeam = () => { + this.setState({ tapCount: this.state.tapCount + 1 }); + if (this.state.tapCount >= 3) { + if (this.state.tapCount == 3) { + // Debug mode on + SetStoreData(DEBUG_MODE, 'true'); + + // Create faux intersection data + let pseudoBin = []; + for (let i = 0; i < 28; i++) { + const intersections = Math.max( + 0, + Math.floor(Math.random() * 50 - 20), + ); + pseudoBin.push(intersections); + } + let dayBin = JSON.stringify(pseudoBin); + SetStoreData(CROSSED_PATHS, dayBin); + } else if (this.state.tapCount == 7) { + // Debug mode off + + // Create faux intersection data + let pseudoBin = []; + for (let i = 0; i < 28; i++) { + pseudoBin.push(0); + } + let dayBin = JSON.stringify(pseudoBin); + SetStoreData(CROSSED_PATHS, dayBin); + + this.setState({ tapCount: 0 }); + SetStoreData(DEBUG_MODE, 'false'); + } + } + }; + render() { return ( - + 3 ? 'red' : null, + }) + } + xml={team} + /> {languages.t('label.team')} @@ -80,11 +136,6 @@ const styles = StyleSheet.create({ alignSelf: 'center', backgroundColor: Colors.WHITE, }, - aboutSectionIconTeam: { - width: 40.38, - height: 19, - marginTop: 36, - }, aboutSectionIconLock: { width: 20, height: 26.67, diff --git a/app/views/LocationTracking.js b/app/views/LocationTracking.js index f11cc22128..0af0ada8ae 100644 --- a/app/views/LocationTracking.js +++ b/app/views/LocationTracking.js @@ -50,7 +50,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'; +import { PARTICIPATE, CROSSED_PATHS, DEBUG_MODE } from '../constants/storage'; const StateEnum = { UNKNOWN: 0, @@ -131,18 +131,23 @@ class LocationTracking extends Component { checkIfUserAtRisk() { BackgroundTaskServices.start(); - // already set on 12h timer, but run when this screen opens too - checkIntersect(); - - GetStoreData('CROSSED_PATHS').then(dayBin => { - dayBin = JSON.parse(dayBin); - if (dayBin !== null && dayBin.reduce((a, b) => a + b, 0) > 0) { - console.log('Found crossed paths'); - this.setState({ currentState: StateEnum.AT_RISK }); - } else { - console.log("Can't find crossed paths"); - this.setState({ currentState: StateEnum.NO_CONTACT }); + + GetStoreData(DEBUG_MODE).then(dbgMode => { + if (dbgMode != 'true') { + // already set on 12h timer, but run when this screen opens too + checkIntersect(); } + + GetStoreData(CROSSED_PATHS).then(dayBin => { + dayBin = JSON.parse(dayBin); + if (dayBin !== null && dayBin.reduce((a, b) => a + b, 0) > 0) { + console.log('Found crossed paths'); + this.setState({ currentState: StateEnum.AT_RISK }); + } else { + console.log("Can't find crossed paths"); + this.setState({ currentState: StateEnum.NO_CONTACT }); + } + }); }); } diff --git a/app/views/Notification.js b/app/views/Notification.js index 56aeb32765..c13fe71892 100644 --- a/app/views/Notification.js +++ b/app/views/Notification.js @@ -18,7 +18,7 @@ import fontFamily from '../constants/fonts'; import backArrow from './../assets/images/backArrow.png'; import languages from './../locales/languages'; import AsyncStorage from '@react-native-community/async-storage'; -import { GetStoreData, SetStoreData } from '../helpers/General'; +import { GetStoreData } from '../helpers/General'; import { VictoryBar, VictoryAxis, @@ -88,16 +88,6 @@ class NotificationScreen extends Component { GetStoreData(CROSSED_PATHS).then(dayBin => { console.log(dayBin); - /* DEBUGGING TOOL -- handy for creating faux data - let pseudoBin = []; - for (var i = 0; i < 28; i++) { - // Random Integer between 0-99 - const intersections = Math.floor((Math.random() * 500) / 300); - pseudoBin.push(intersections); - } - dayBin = JSON.stringify(pseudoBin); - */ - if (dayBin === null) { this.setState({ dataAvailable: false }); console.log("Can't found Crossed Paths"); From d88b8e2eb35acb9fd3e6c0e1f93861b47b8eac67 Mon Sep 17 00:00:00 2001 From: Steve Penrod Date: Mon, 13 Apr 2020 19:37:59 -0500 Subject: [PATCH 2/9] On exit, intersection 4-tap mode now restores When leaving the About box 4-tap faux intersection mode, the app now performs a intersection() calculation again to restore the data fully. --- app/views/About.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/About.js b/app/views/About.js index 57c12a6deb..b2107ae1fb 100644 --- a/app/views/About.js +++ b/app/views/About.js @@ -11,6 +11,7 @@ import { SvgXml } from 'react-native-svg'; import lock from '../assets/svgs/lock'; import { GetStoreData, SetStoreData } from '../helpers/General'; import { DEBUG_MODE, CROSSED_PATHS } from '../constants/storage'; +import { checkIntersect } from '../helpers/Intersect'; class AboutScreen extends Component { constructor(props) { @@ -65,7 +66,7 @@ class AboutScreen extends Component { } else if (this.state.tapCount == 7) { // Debug mode off - // Create faux intersection data + // Wipe faux intersection data let pseudoBin = []; for (let i = 0; i < 28; i++) { pseudoBin.push(0); @@ -75,6 +76,9 @@ class AboutScreen extends Component { this.setState({ tapCount: 0 }); SetStoreData(DEBUG_MODE, 'false'); + + // Kick off intersection calculations to restore data + checkIntersect(); } } }; From 9fd0fc44ffb8c359a4f5ed7d005d07173461447e Mon Sep 17 00:00:00 2001 From: Steve Penrod Date: Mon, 13 Apr 2020 20:05:49 -0500 Subject: [PATCH 3/9] Changes based on review feedback * Magic numbers to consts * Add red message when in demo mode * Remove unnecessary bind --- app/views/About.js | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/app/views/About.js b/app/views/About.js index b2107ae1fb..aa7505c784 100644 --- a/app/views/About.js +++ b/app/views/About.js @@ -13,6 +13,8 @@ import { GetStoreData, SetStoreData } from '../helpers/General'; import { DEBUG_MODE, CROSSED_PATHS } from '../constants/storage'; import { checkIntersect } from '../helpers/Intersect'; +const dayBinSize = 28; // Number of day in the standard day-bin array (4 weeks) + class AboutScreen extends Component { constructor(props) { super(props); @@ -54,7 +56,7 @@ class AboutScreen extends Component { // Create faux intersection data let pseudoBin = []; - for (let i = 0; i < 28; i++) { + for (let i = 0; i < dayBinSize; i++) { const intersections = Math.max( 0, Math.floor(Math.random() * 50 - 20), @@ -68,7 +70,7 @@ class AboutScreen extends Component { // Wipe faux intersection data let pseudoBin = []; - for (let i = 0; i < 28; i++) { + for (let i = 0; i < dayBinSize; i++) { pseudoBin.push(0); } let dayBin = JSON.stringify(pseudoBin); @@ -101,19 +103,23 @@ class AboutScreen extends Component { {languages.t('label.commitment_para')} - 3 ? 'red' : null, - }) - } - xml={team} - /> + + + {this.state.tapCount > 3 ? 'In exposure demo mode' : null} + + 3 ? 'red' : null, + }) + } + xml={team} + /> + {languages.t('label.team')} From 92b16883adeb6dcdb18661d176112a7070ef0a42 Mon Sep 17 00:00:00 2001 From: Steve Penrod Date: Mon, 13 Apr 2020 20:27:03 -0500 Subject: [PATCH 4/9] Resolve merge issue --- app/views/Notification.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/views/Notification.js b/app/views/Notification.js index 8567d6f416..3b4b51fee3 100644 --- a/app/views/Notification.js +++ b/app/views/Notification.js @@ -13,12 +13,6 @@ import { VictoryAxis, VictoryBar, VictoryChart } from 'victory-native'; import languages from './../locales/languages'; import AsyncStorage from '@react-native-community/async-storage'; import { GetStoreData } from '../helpers/General'; -import { - VictoryBar, - VictoryAxis, - VictoryChart, - VictoryTooltip, -} from 'victory-native'; import Colors from '../constants/colors'; import NavigationBarWrapper from '../components/NavigationBarWrapper'; import colors from '../constants/colors'; From e3a9e14760eb06d17eea69ac7d419cdc1d0d11a3 Mon Sep 17 00:00:00 2001 From: Steve Penrod Date: Mon, 13 Apr 2020 20:45:51 -0500 Subject: [PATCH 5/9] Fix merge issue --- app/views/Notification.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/views/Notification.js b/app/views/Notification.js index 3b4b51fee3..69ead56c78 100644 --- a/app/views/Notification.js +++ b/app/views/Notification.js @@ -13,7 +13,6 @@ import { VictoryAxis, VictoryBar, VictoryChart } from 'victory-native'; import languages from './../locales/languages'; import AsyncStorage from '@react-native-community/async-storage'; import { GetStoreData } from '../helpers/General'; -import Colors from '../constants/colors'; import NavigationBarWrapper from '../components/NavigationBarWrapper'; import colors from '../constants/colors'; import Colors from '../constants/colors'; From 93c0b12be783bab9468785d480f41876e6fa40d9 Mon Sep 17 00:00:00 2001 From: Steve Penrod Date: Mon, 13 Apr 2020 20:50:15 -0500 Subject: [PATCH 6/9] Fix merge conflict --- app/views/Notification.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/views/Notification.js b/app/views/Notification.js index 69ead56c78..3f9d440aa3 100644 --- a/app/views/Notification.js +++ b/app/views/Notification.js @@ -12,7 +12,6 @@ import { VictoryAxis, VictoryBar, VictoryChart } from 'victory-native'; import languages from './../locales/languages'; import AsyncStorage from '@react-native-community/async-storage'; -import { GetStoreData } from '../helpers/General'; import NavigationBarWrapper from '../components/NavigationBarWrapper'; import colors from '../constants/colors'; import Colors from '../constants/colors'; From 57ece21cfa8ea6c7cdac5ce02c99641176cfc165 Mon Sep 17 00:00:00 2001 From: Steve Penrod Date: Mon, 13 Apr 2020 21:03:30 -0500 Subject: [PATCH 7/9] Fix some lint --- app/views/About.js | 2 +- app/views/Notification.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/About.js b/app/views/About.js index 21cd20bbae..0af5452005 100644 --- a/app/views/About.js +++ b/app/views/About.js @@ -104,7 +104,7 @@ class AboutScreen extends Component { - + {this.state.tapCount > 3 ? 'In exposure demo mode' : null} Date: Sat, 18 Apr 2020 13:01:58 -0700 Subject: [PATCH 8/9] Move debug logic into Intersect.js, added tap to disable --- app/helpers/Intersect.js | 40 ++++++++++++++++++-- app/views/About.js | 80 +++++++++++++++------------------------- 2 files changed, 66 insertions(+), 54 deletions(-) diff --git a/app/helpers/Intersect.js b/app/helpers/Intersect.js index 604a99edb1..9dc4c1b9fe 100644 --- a/app/helpers/Intersect.js +++ b/app/helpers/Intersect.js @@ -8,12 +8,13 @@ import PushNotification from 'react-native-push-notification'; import { isPlatformiOS } from './../Util'; import { - LOCATION_DATA, - CROSSED_PATHS, - AUTHORITY_SOURCE_SETTINGS, AUTHORITY_NEWS, + AUTHORITY_SOURCE_SETTINGS, + CROSSED_PATHS, LAST_CHECKED, + LOCATION_DATA, } from '../constants/storage'; +import { DEBUG_MODE } from '../constants/storage'; import { GetStoreData, SetStoreData } from '../helpers/General'; import languages from '../locales/languages'; @@ -293,3 +294,36 @@ export function checkIntersect() { }) .catch(error => console.log('Failed to load authority list', error)); } + +/** Number of day in the standard day-bin array (4 weeks) */ +const DAY_BIN_SIZE = 28; + +/** Set the app into debug mode */ +export function enableDebugMode() { + SetStoreData(DEBUG_MODE, 'true'); + + // Create faux intersection data + let pseudoBin = []; + for (let i = 0; i < DAY_BIN_SIZE; i++) { + const intersections = Math.max(0, Math.floor(Math.random() * 50 - 20)); + pseudoBin.push(intersections); + } + let dayBin = JSON.stringify(pseudoBin); + SetStoreData(CROSSED_PATHS, dayBin); +} + +/** Restore the app from debug mode */ +export function disableDebugMode() { + // Wipe faux intersection data + let pseudoBin = []; + for (let i = 0; i < DAY_BIN_SIZE; i++) { + pseudoBin.push(0); + } + let dayBin = JSON.stringify(pseudoBin); + SetStoreData(CROSSED_PATHS, dayBin); + + SetStoreData(DEBUG_MODE, 'false'); + + // Kick off intersection calculations to restore data + checkIntersect(); +} diff --git a/app/views/About.js b/app/views/About.js index 258ca1c9d3..b5496e877b 100644 --- a/app/views/About.js +++ b/app/views/About.js @@ -8,21 +8,19 @@ import { Text, View, } from 'react-native'; +import { TouchableOpacity } from 'react-native-gesture-handler'; import { SvgXml } from 'react-native-svg'; import packageJson from '../../package.json'; import team from './../assets/svgs/team'; import fontFamily from './../constants/fonts'; import languages from './../locales/languages'; -import { isPlatformiOS } from './../Util'; import lock from '../assets/svgs/lock'; import NavigationBarWrapper from '../components/NavigationBarWrapper'; import Colors from '../constants/colors'; -import { CROSSED_PATHS, DEBUG_MODE } from '../constants/storage'; -import { GetStoreData, SetStoreData } from '../helpers/General'; -import { checkIntersect } from '../helpers/Intersect'; - -const dayBinSize = 28; // Number of day in the standard day-bin array (4 weeks) +import { DEBUG_MODE } from '../constants/storage'; +import { GetStoreData } from '../helpers/General'; +import { disableDebugMode, enableDebugMode } from '../helpers/Intersect'; class AboutScreen extends Component { constructor(props) { @@ -60,40 +58,19 @@ class AboutScreen extends Component { this.setState({ tapCount: this.state.tapCount + 1 }); if (this.state.tapCount >= 3) { if (this.state.tapCount == 3) { - // Debug mode on - SetStoreData(DEBUG_MODE, 'true'); - - // Create faux intersection data - let pseudoBin = []; - for (let i = 0; i < dayBinSize; i++) { - const intersections = Math.max( - 0, - Math.floor(Math.random() * 50 - 20), - ); - pseudoBin.push(intersections); - } - let dayBin = JSON.stringify(pseudoBin); - SetStoreData(CROSSED_PATHS, dayBin); + enableDebugMode(); } else if (this.state.tapCount == 7) { - // Debug mode off - - // Wipe faux intersection data - let pseudoBin = []; - for (let i = 0; i < dayBinSize; i++) { - pseudoBin.push(0); - } - let dayBin = JSON.stringify(pseudoBin); - SetStoreData(CROSSED_PATHS, dayBin); - this.setState({ tapCount: 0 }); - SetStoreData(DEBUG_MODE, 'false'); - - // Kick off intersection calculations to restore data - checkIntersect(); + disableDebugMode(); } } }; + handleDebugModePress = () => { + this.setState({ tapCount: 0 }); + disableDebugMode(); + }; + render() { return ( - - - {this.state.tapCount > 3 ? 'In exposure demo mode' : null} - + 3 ? 'red' : null, - }) - } + style={styles.aboutSectionIconTeam} xml={team} + stroke={this.state.tapCount > 3 ? 'red' : undefined} /> + {this.state.tapCount > 3 && ( + + + In exposure demo mode, tap to disable + + + )} {languages.t('label.team')} @@ -180,11 +160,9 @@ const styles = StyleSheet.create({ // flex: 1, paddingBottom: 42, }, - section: { - flexDirection: 'column', - width: '87.5%', - alignSelf: 'center', - backgroundColor: Colors.WHITE, + aboutSectionIconTeam: { + width: 40.38, + height: 19, }, aboutSectionIconLock: { width: 20, From 60f81f2389317daf0c026a9d213ff9cb5f2d0ccb Mon Sep 17 00:00:00 2001 From: Tim Stirrat Date: Sat, 18 Apr 2020 15:40:12 -0700 Subject: [PATCH 9/9] Disable degug mode in release builds --- app/views/About.js | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/app/views/About.js b/app/views/About.js index b5496e877b..fcb86eaade 100644 --- a/app/views/About.js +++ b/app/views/About.js @@ -55,18 +55,21 @@ class AboutScreen extends Component { } handleTapTeam = () => { - this.setState({ tapCount: this.state.tapCount + 1 }); - if (this.state.tapCount >= 3) { - if (this.state.tapCount == 3) { - enableDebugMode(); - } else if (this.state.tapCount == 7) { - this.setState({ tapCount: 0 }); - disableDebugMode(); + // debug builds only until we have feature flagging. + if (__DEV__) { + this.setState({ tapCount: this.state.tapCount + 1 }); + if (this.state.tapCount >= 3) { + if (this.state.tapCount == 3) { + enableDebugMode(); + } else if (this.state.tapCount == 7) { + this.setState({ tapCount: 0 }); + disableDebugMode(); + } } } }; - handleDebugModePress = () => { + handleExitDebugModePress = () => { this.setState({ tapCount: 0 }); disableDebugMode(); }; @@ -101,8 +104,16 @@ class AboutScreen extends Component { stroke={this.state.tapCount > 3 ? 'red' : undefined} /> {this.state.tapCount > 3 && ( - - + + In exposure demo mode, tap to disable