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 an EULA to the onboarding process #638

Merged
merged 35 commits into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cb8893e
Add components, layout, nav for EULA modal
SamMakesThings Apr 22, 2020
7a0e54d
Disable button when box isn't checked
SamMakesThings Apr 22, 2020
f3f379a
Add markdown render library & test to EULA modal
SamMakesThings Apr 22, 2020
9c5b657
Add basic EULA style, add nav after agreement
SamMakesThings Apr 22, 2020
e36343c
Add EULA strings to the translation system
SamMakesThings Apr 22, 2020
7ba7d3f
Turn into function component, named export
SamMakesThings Apr 23, 2020
fd8b7a6
Extract Checkbox component into own file
SamMakesThings Apr 23, 2020
802170a
Use Typography instead of Text
SamMakesThings Apr 23, 2020
d017044
Use the reactive t instead of languages.t
SamMakesThings Apr 23, 2020
5ab407c
Move EULA text into an i18n group (onboarding)
SamMakesThings Apr 23, 2020
a7d521f
Remove duplicate translation keys
SamMakesThings Apr 23, 2020
87abc65
Move EULA md into file for each language
SamMakesThings Apr 23, 2020
f438a36
Merge branch 'develop' into pr/StartupSam/638
tstirrat Apr 24, 2020
2c8e27e
Change es to ht
tstirrat Apr 24, 2020
bbf0fa3
Fix loading of user local override
tstirrat Apr 24, 2020
fbce7af
Use theme for checkbox
tstirrat Apr 24, 2020
8bd5c91
Use safeareaview to prevent going into unsafe area on ioS
tstirrat Apr 24, 2020
cbf2715
remove unused en.json key
tstirrat Apr 24, 2020
08fd339
Less top padding on EULA modal
tstirrat Apr 24, 2020
49efec2
Update eula text
tstirrat Apr 24, 2020
a59e0d7
Import fix
tstirrat Apr 24, 2020
df7f498
EULA text
tstirrat Apr 24, 2020
e624e34
revert eula, it was broken anyway
tstirrat Apr 24, 2020
9bf3347
Remove Markdown usage
tstirrat Apr 24, 2020
a5592e8
remove markdown lib
tstirrat Apr 24, 2020
f1d27da
haitian translations
tstirrat Apr 24, 2020
20fb0b4
Update e2e tests
Patrick-Erichsen Apr 24, 2020
5e26ec5
Merge branch 'eula-add' of github.com:StartupSam/private-kit into pr/…
Patrick-Erichsen Apr 24, 2020
05a3c67
Merge branch 'develop' into pr/StartupSam/638
tstirrat Apr 24, 2020
9b9f3ec
Componentize Checkbox better
tstirrat Apr 24, 2020
af7f4ec
Initial
tstirrat Apr 24, 2020
39e3ea7
Remove webview props
tstirrat Apr 24, 2020
bc7fa47
Detect scroll on EULA before enable continue button
tstirrat Apr 24, 2020
737c038
comments!
tstirrat Apr 24, 2020
48b2ab6
Latest Creole EULA export
tstirrat Apr 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added app/assets/images/boxCheckedIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/boxUncheckedIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion app/components/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Button extends React.Component {
buttonStyle,
buttonHeight = 54,
borderColor,
disabled,
} = this.props;
return (
<LinearGradient
Expand All @@ -40,7 +41,8 @@ class Button extends React.Component {
onPress={onPress}
accessible
accessibilityLabel={title}
accessibilityRole='button'>
accessibilityRole='button'
disabled={disabled}>
<Typography
style={[
titleStyle ? titleStyle : styles.text,
Expand Down
23 changes: 23 additions & 0 deletions app/components/Checkbox.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';
tstirrat marked this conversation as resolved.
Show resolved Hide resolved
import { useTranslation } from 'react-i18next';
import { Image, TouchableOpacity } from 'react-native';

import boxCheckedIcon from './../assets/images/boxCheckedIcon.png';
import boxUncheckedIcon from './../assets/images/boxUncheckedIcon.png';
import { Typography } from './Typography';

export const Checkbox = props => {
const { t } = useTranslation();

return (
<TouchableOpacity
style={{ flexDirection: 'row' }}
onPress={props.onPressFunction}>
<Image
source={props.boxChecked === true ? boxCheckedIcon : boxUncheckedIcon}
style={{ width: 25, height: 25, marginRight: 10 }}
/>
<Typography use='body1'>{t('onboarding.eula_checkbox')}</Typography>
</TouchableOpacity>
);
};
110 changes: 110 additions & 0 deletions app/components/EulaModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
Image,
Modal,
StyleSheet,
Text,
TouchableOpacity,
View,
} from 'react-native';
import { ScrollView } from 'react-native-gesture-handler';
import { SafeAreaView } from 'react-native-safe-area-context';

import closeIcon from '../assets/images/closeIcon.png';
import colors from '../constants/colors';
import Colors from '../constants/colors';
import { Theme } from '../constants/themes';
import ButtonWrapper from './ButtonWrapper';
import { Checkbox } from './Checkbox';
import { Typography } from './Typography';

const eula_en = <Text>English</Text>;

const EULA_LANGUAGES = {
en: eula_en,
ht: <Text>Haitian</Text>,
};

export const EulaModal = ({ selectedLocale, continueFunction }) => {
const [modalVisible, setModalVisibility] = useState(false);
const [boxChecked, toggleCheckbox] = useState(false);
const { t } = useTranslation();

// Pull the EULA in the correct language, with en as fallback
const eulaText = EULA_LANGUAGES[selectedLocale] || eula_en;

return (
<>
<ButtonWrapper
title={t('label.launch_get_started')}
onPress={() => setModalVisibility(true)}
buttonColor={Colors.VIOLET}
bgColor={Colors.WHITE}
/>
<Modal animationType='slide' transparent visible={modalVisible}>
<View style={styles.container}>
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 7, paddingHorizontal: 25, paddingBottom: 0 }}>
<TouchableOpacity onPress={() => setModalVisibility(false)}>
<Image source={closeIcon} style={styles.closeIcon} />
</TouchableOpacity>
<ScrollView>{eulaText}</ScrollView>
</View>
</SafeAreaView>
<Theme use='violet'>
<SafeAreaView style={{ backgroundColor: Colors.VIOLET_BUTTON }}>
<View style={styles.ctaBox}>
<Checkbox
onPressFunction={() => toggleCheckbox(!boxChecked)}
boxChecked={boxChecked}
/>
<Typography style={styles.smallDescriptionText}>
{t('onboarding.eula_message')}
</Typography>
<ButtonWrapper
title={t('onboarding.eula_continue')}
buttonColor={boxChecked ? Colors.VIOLET : Colors.GRAY_BUTTON}
bgColor={boxChecked ? Colors.WHITE : Colors.LIGHT_GRAY}
buttonWidth={'100%'}
disabled={!boxChecked}
onPress={() => {
setModalVisibility(false);
continueFunction();
}}
/>
</View>
</SafeAreaView>
</Theme>
</View>
</Modal>
</>
);
};

const styles = StyleSheet.create({
// Container covers the entire screen
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between',
color: colors.PRIMARY_TEXT,
backgroundColor: colors.WHITE,
},
ctaBox: {
padding: 25,
paddingTop: 0,
backgroundColor: Colors.VIOLET_BUTTON,
},
closeIcon: {
width: 20,
height: 20,
marginBottom: 6,
opacity: 0.7,
alignSelf: 'flex-end',
},
smallDescriptionText: {
fontSize: 14,
tstirrat marked this conversation as resolved.
Show resolved Hide resolved
marginVertical: 12,
},
});
18 changes: 6 additions & 12 deletions app/locales/en.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
{
"history": {
"no_exposure": "No exposure",
"possible_exposure": "Possible exposure",
"possible_exposure_para": "It is possible you were in contact with or close to someone who tested positive for COVID-19",
"what_does_this_mean": "What does this mean?",
"what_does_this_mean_para": "Based on your GPS history, it is possible that you may have been in contact with or close to somebody who was diagnosed with COVID-19. This does not mean you are infected but that you might be.\n\nFor further information on what you should do you can refer to the Mayo Clinic’s website.",
"what_if_no_symptoms": "What if I’m not showing symptoms?",
"what_if_no_symptoms_para": "If you have no symptoms but still would like to be tested you can go to your nearest testing site.\n\nIndividuals who don't exhibit symptoms can sometimes still carry the infection and infect others. Being careful about social distancing and coming in contact with large groups or at risk individuals (the elderly, those with significant other medical issues) is important to manage both your risk and the risk to others."
},
"label": {
"about_title": "About",
"authorities_add_button_label": "Add Trusted Source",
Expand Down Expand Up @@ -94,8 +85,6 @@
"terms_of_use_url": "https://docs.google.com/document/d/1mtdal_pywsKZVMXLHjjj5eKznipPLP8sM1HwFTIhjo0/edit#",
"tested_positive_subtitle": "Your private data can be transferred to health authorities, backed up, or otherwise shared.",
"tested_positive_title": "Share location history",
"logging_active": "Location Active",
"logging_inactive": "Location Inactive",
"language_change_alert_title": "App need to restart in order to use this language",
"language_change_alert_proced": "Restart",
"language_change_alert_cancel": "Cancel"
Expand All @@ -109,5 +98,10 @@
"what_does_this_mean": "What does this mean?",
"what_if_no_symptoms_para": "If you have no symptoms but still would like to be tested you can go to your nearest testing site.\n\nIndividuals who don't exhibit symptoms can sometimes still carry the infection and infect others. Being careful about social distancing and coming in contact with large groups or at risk individuals (the elderly, those with significant other medical issues) is important to manage both your risk and the risk to others.",
"what_if_no_symptoms": "What if I’m not showing symptoms?"
},
"onboarding": {
"eula_checkbox": "I accept the licensing agreement",
"eula_message": "*You must accept in order to use Safe Paths",
"eula_continue": "Continue"
}
}
}
4 changes: 4 additions & 0 deletions app/locales/eula/eula_en.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const eula_en = `**Terms of Use**

**Last Updated Date: April 23, 2020**
`;
4 changes: 4 additions & 0 deletions app/locales/eula/eula_ht.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const eula_ht = `**COVID Safe Paths**

**Tradiksyon ayisyen isit la**
`;
7 changes: 6 additions & 1 deletion app/locales/ht.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"default_news_site_name": "Nouvèl sou Chase Kowona (\"Safe Paths\")",
"event_history_subtitle": "Konprann ekspozisyon pèsonèl ou daprè enfòmasyon Otorite a pataje.",
"event_history_title": "Lis ekspozisyon",
"export_para_1": "Si ou teste pozitif pou Kowonaviris, tanpri fè pati pa ou a nan pataje lis lokalizasyon ou ak otorite lokal yo.",
"export_para_1": "Si ou teste pozitif pou Kowonaviris, tanpri fè pati pa ou a nan pataje lis lokalizasyon ou ak otorite lokal yo.",
"export_para_2": "Lokalizasyon ou yo ap pataje sou fòm yon senp lis lè ak zòn, pap gen okenn enfòmasyon anplis ki prale.",
"home_at_risk_header": "Ou ka gen risk",
"home_at_risk_subsubtext": "Sa pa vle di ou enfekte.",
Expand Down Expand Up @@ -112,5 +112,10 @@
"terms_of_use": "Règleman itilizasyon",
"tested_positive_subtitle": "Done prive ou kapab transfere a Otorite a, konsève, oubyen pataje.",
"tested_positive_title": "Pataje lis lokalizasyon"
},
"onboarding": {
"eula_checkbox": "Mwen aksepte akò lisans la",
"eula_message": "*Ou dwe aksepte pou itilize Safe Paths 'Chase Kowona",
"eula_continue": "Kontinye"
}
}
24 changes: 14 additions & 10 deletions app/views/onboarding/Onboarding1.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import languages, {
setUserLocaleOverride,
supportedDeviceLanguageOrEnglish,
} from './../../locales/languages';
import ButtonWrapper from '../../components/ButtonWrapper';
import { EulaModal } from '../../components/EulaModal';
import NativePicker from '../../components/NativePicker';
import { Typography } from '../../components/Typography';
import Colors from '../../constants/colors';
import fontFamily from '../../constants/fonts';
import { Typography } from '../../components/Typography';

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

Expand All @@ -34,8 +34,10 @@ class Onboarding extends Component {
}

componentDidMount() {
getUserLocaleOverride(locale => {
this.setState({ locale });
getUserLocaleOverride().then(locale => {
if (locale) {
this.setState({ locale });
}
});
}

Expand Down Expand Up @@ -77,7 +79,9 @@ class Onboarding extends Component {
<TouchableOpacity
onPress={openPicker}
style={styles.languageSelector}>
<Typography style={styles.languageSelectorText}>{label}</Typography>
<Typography style={styles.languageSelectorText}>
{label}
</Typography>
</TouchableOpacity>
)}
</NativePicker>
Expand All @@ -88,11 +92,11 @@ class Onboarding extends Component {
</Typography>
</View>
<View style={styles.footerContainer}>
<ButtonWrapper
title={languages.t('label.launch_get_started')}
onPress={() => this.props.navigation.replace('Onboarding2')}
buttonColor={Colors.VIOLET}
bgColor={Colors.WHITE}
<EulaModal
continueFunction={() =>
this.props.navigation.replace('Onboarding2')
}
selectedLocale={this.state.locale}
/>
</View>
</View>
Expand Down
5 changes: 5 additions & 0 deletions e2e/Onboarding.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Onboarding1 from './pages/Onboarding1.po.js';
import Onboarding2 from './pages/Onboarding2.po.js';
import Onboarding3 from './pages/Onboarding3.po.js';
import Onboarding4 from './pages/Onboarding4.po.js';
import SignEula from './pages/SignEula.po.js';

describe('Onboarding visual appearance', () => {
it('Navigates through the onboarding without visual regression', async () => {
Expand All @@ -14,6 +15,10 @@ describe('Onboarding visual appearance', () => {
await Onboarding1.takeScreenshot();
await Onboarding1.tapButton();

await SignEula.sign();
await SignEula.takeScreenshot();
await SignEula.tapButton();

await Onboarding2.isOnScreen();
await Onboarding2.takeScreenshot();
await Onboarding2.tapButton();
Expand Down
19 changes: 19 additions & 0 deletions e2e/UnsignedEula.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Onboarding1 from './pages/Onboarding1.po.js';
import SignEula from './pages/SignEula.po.js';

describe('Cannot continue without signing the EULA', () => {
beforeAll(async () => {
await device.launchApp({
newInstance: true,
});
});

it('Does not allow the user to proceed', async () => {
await Onboarding1.isOnScreen();
await Onboarding1.tapButton();

await SignEula.tapButton();
await SignEula.takeScreenshot();
await device.takeScreenshot('Unsigned Eula Continue Attempt');
});
});
4 changes: 4 additions & 0 deletions e2e/helpers/onboarding.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import Onboarding1 from '../pages/Onboarding1.po.js';
import Onboarding2 from '../pages/Onboarding2.po.js';
import Onboarding3 from '../pages/Onboarding3.po.js';
import Onboarding4 from '../pages/Onboarding4.po.js';
import SignEula from '../pages/SignEula.po.js';

export const navigateThroughOnboarding = async () => {
await Onboarding1.isOnScreen();
await Onboarding1.tapButton();

await SignEula.sign();
await SignEula.tapButton();

await Onboarding2.isOnScreen();
await Onboarding2.tapButton();

Expand Down
20 changes: 20 additions & 0 deletions e2e/pages/SignEula.po.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* eslint-disable */
const buttonlabel = 'Continue';
const signCheckboxLabel = 'I accept the licensing agreement';
const screenshotText = 'EULA Accept Page';

class SignEula {
async tapButton() {
await element(by.label(buttonlabel)).tap();
}

async sign() {
await element(by.text(signCheckboxLabel)).tap();
}

async takeScreenshot() {
await device.takeScreenshot(screenshotText);
}
}

export default new SignEula();