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

Add a debug mode for intersections #437

Merged
merged 12 commits into from
Apr 18, 2020
4 changes: 2 additions & 2 deletions app/components/__tests__/Typography.spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import React from 'react';

import { Typography } from '../Typography';
import { Theme } from '../../constants/themes';
import { Typography } from '../Typography';

it('headline1 is large and bold', () => {
const { asJSON } = render(
Expand Down
1 change: 1 addition & 0 deletions app/constants/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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';
export const AUTHORITY_NEWS = 'AUTHORITY_NEWS';
export const LAST_CHECKED = 'LAST_CHECKED';
export const AUTHORITY_SOURCE_SETTINGS = 'AUTHORITY_SOURCE_SETTINGS';
40 changes: 37 additions & 3 deletions app/helpers/Intersect.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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();
}
70 changes: 60 additions & 10 deletions app/views/About.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,25 @@ 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 { DEBUG_MODE } from '../constants/storage';
import { GetStoreData } from '../helpers/General';
import { disableDebugMode, enableDebugMode } from '../helpers/Intersect';

class AboutScreen extends Component {
constructor(props) {
super(props);
this.state = {
//
tapCount: 0, // tracks number of taps, for debugging
};
}

Expand All @@ -32,18 +35,45 @@ 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);
}

componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress);
}

handleTapTeam = () => {
// 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();
}
}
}
};

handleExitDebugModePress = () => {
this.setState({ tapCount: 0 });
disableDebugMode();
};

render() {
return (
<NavigationBarWrapper
Expand All @@ -61,7 +91,34 @@ class AboutScreen extends Component {
{languages.t('label.commitment_para')}
</Text>

<SvgXml style={styles.aboutSectionIconTeam} xml={team} />
<View
style={{
flexDirection: 'row',
alignContent: 'center',
marginTop: 36,
}}>
<SvgXml
onPress={this.handleTapTeam}
style={styles.aboutSectionIconTeam}
xml={team}
stroke={this.state.tapCount > 3 ? 'red' : undefined}
/>
{this.state.tapCount > 3 && (
<TouchableOpacity onPress={this.handleExitDebugModePress}>
<Text
style={{
color: Colors.RED_TEXT,
marginLeft: 12,
borderRadius: 4,
backgroundColor: 'rgba(255, 0, 0, 0.2)',
paddingHorizontal: 8,
paddingVertical: 2,
}}>
In exposure demo mode, tap to disable
</Text>
</TouchableOpacity>
)}
</View>
<Text style={styles.aboutSectionTitles}>
{languages.t('label.team')}
</Text>
Expand Down Expand Up @@ -114,16 +171,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,
marginTop: 36,
},
aboutSectionIconLock: {
width: 20,
Expand Down
16 changes: 0 additions & 16 deletions app/views/ExposureHistory/ExposureHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ export const ExposureHistoryScreen = ({ navigation }) => {
async function fetchData() {
let dayBins = await GetStoreData(CROSSED_PATHS);

// dayBins = generateFakeIntersections(1); // handy for creating faux data

if (dayBins === null) {
setHistory(NO_HISTORY);
console.log("Can't find Crossed Paths");
Expand Down Expand Up @@ -84,20 +82,6 @@ export const ExposureHistoryScreen = ({ navigation }) => {
);
};

// eslint-disable-next-line no-unused-vars
function generateFakeIntersections(days = MAX_EXPOSURE_WINDOW, maxBins = 50) {
let pseudoBin = [];
for (let i = 0; i < days; i++) {
// Random Integer between 0-99
const intersections = Math.max(
Math.floor(Math.random() * maxBins - maxBins / 2),
0,
);
pseudoBin.push(intersections);
}
return JSON.stringify(pseudoBin);
}

/**
* Convert the daily "bins" payload to an array of daily minutes of exposure.
*
Expand Down
11 changes: 6 additions & 5 deletions app/views/ExposureHistory/SingleExposureDetail.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import dayjs from 'dayjs';
import React from 'react';
import styled from '@emotion/native';
import { CalendarDay } from './CalendarDay';
import languages from '../../locales/languages';
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
import relativeTime from 'dayjs/plugin/relativeTime';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import relativeTime from 'dayjs/plugin/relativeTime';
import React from 'react';

import languages from '../../locales/languages';
import { CalendarDay } from './CalendarDay';

dayjs.extend(relativeTime);
dayjs.extend(duration);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import dayjs from 'dayjs';
import React from 'react';

import { SingleExposureDetail } from '../SingleExposureDetail';

Expand Down
29 changes: 17 additions & 12 deletions app/views/LocationTracking.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { isPlatformAndroid, isPlatformiOS } from './../Util';
import ButtonWrapper from '../components/ButtonWrapper';
import Colors from '../constants/colors';
import fontFamily from '../constants/fonts';
import { PARTICIPATE } from '../constants/storage';
import { CROSSED_PATHS, DEBUG_MODE, PARTICIPATE } from '../constants/storage';
import { GetStoreData, SetStoreData } from '../helpers/General';
import { checkIntersect } from '../helpers/Intersect';
import languages from '../locales/languages';
Expand Down Expand Up @@ -139,18 +139,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 });
}
});
});

// If the user has location tracking disabled, set enum to match
Expand Down