Skip to content

Commit

Permalink
Introduce escrow flow navigation stack (#734)
Browse files Browse the repository at this point in the history
Why:
We would like to be able to allow the user to navigate through the
escrow verification code flow

This commit:
Introduces the navigation stack and the first screen of the escrow
verification code flow.

Co-Authored-By: Matt Buckley <matt@nicethings.io>
Co-Authored-By: Devin Jameson <devin@thoughtbot.com>
  • Loading branch information
3 people committed Dec 7, 2020
1 parent 0b6d43d commit 7d57b15
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 5 deletions.
59 changes: 59 additions & 0 deletions src/EscrowVerification/EscrowVerificationContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, {
FunctionComponent,
createContext,
useState,
useContext,
} from "react"

import { ExposureKey } from "../exposureKey"

type Token = string
type Key = string

export interface EscrowVerificationContextState {
certificate: Token | null
hmacKey: Key | null
exposureKeys: ExposureKey[]
setExposureKeys: (keys: ExposureKey[]) => void
setExposureSubmissionCredentials: (certificate: Token, hmacKey: Key) => void
}

export const EscrowVerificationContext = createContext<
EscrowVerificationContextState | undefined
>(undefined)

export const EscrowVerificationProvider: FunctionComponent = ({ children }) => {
const [exposureKeys, setExposureKeys] = useState<ExposureKey[]>([])
const [hmacKey, setHmacKey] = useState<Key | null>(null)
const [certificate, setCertificate] = useState<Token | null>(null)

const setExposureSubmissionCredentials = (
certificate: Token,
hmacKey: Key,
) => {
setCertificate(certificate)
setHmacKey(hmacKey)
}

return (
<EscrowVerificationContext.Provider
value={{
hmacKey,
certificate,
exposureKeys,
setExposureKeys,
setExposureSubmissionCredentials,
}}
>
{children}
</EscrowVerificationContext.Provider>
)
}

export const useEscrowVerificationContext = (): EscrowVerificationContextState => {
const context = useContext(EscrowVerificationContext)
if (context === undefined) {
throw new Error("EscrowVerificationContext must be used with a provider")
}
return context
}
123 changes: 123 additions & 0 deletions src/EscrowVerification/Start.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React, { FunctionComponent } from "react"
import {
StyleSheet,
View,
Image,
ScrollView,
TouchableOpacity,
} from "react-native"
import { useTranslation } from "react-i18next"
import { SvgXml } from "react-native-svg"

import { useStatusBarEffect } from "../navigation"
import { Text } from "../components"

import { Spacing, Colors, Typography, Buttons, Iconography } from "../styles"
import { Icons, Images } from "../assets"

export const Start: FunctionComponent = () => {
useStatusBarEffect("dark-content", Colors.background.primaryLight)
const { t } = useTranslation()

const handleOnPressContinue = () => {}

const handleOnPressSecondaryButton = () => {}

return (
<ScrollView
style={style.container}
contentContainerStyle={style.contentContainer}
alwaysBounceVertical={false}
>
<View>
<Image
source={Images.HowItWorksValueProposition}
style={style.image}
accessible
accessibilityLabel={t("escrow_verification.person_and_health_expert")}
/>
<Text style={style.headerText}>
{t("escrow_verification.start.header")}
</Text>
<Text style={style.bodyText}>
{t("escrow_verification.start.body")}
</Text>
</View>
<View>
<TouchableOpacity
style={style.button}
onPress={handleOnPressContinue}
accessibilityLabel={t("common.continue")}
>
<Text style={style.buttonText}>{t("common.continue")}</Text>
<SvgXml xml={Icons.Arrow} fill={Colors.background.primaryLight} />
</TouchableOpacity>
<TouchableOpacity
style={style.secondaryButton}
onPress={handleOnPressSecondaryButton}
accessibilityLabel={t("export.intro.what_is_a")}
>
<View style={style.secondaryButtonIconContainer}>
<SvgXml
xml={Icons.QuestionMark}
fill={Colors.primary.shade125}
width={Iconography.xxxSmall}
height={Iconography.xxxSmall}
/>
</View>
<Text style={style.secondaryButtonText}>
{t("escrow_verification.start.what_is_a_verification_code")}
</Text>
</TouchableOpacity>
</View>
</ScrollView>
)
}

const imageSize = 140

const style = StyleSheet.create({
container: {
backgroundColor: Colors.background.primaryLight,
},
contentContainer: {
flexGrow: 1,
justifyContent: "space-between",
paddingHorizontal: Spacing.large,
paddingBottom: Spacing.xxLarge,
backgroundColor: Colors.background.primaryLight,
},
image: {
resizeMode: "contain",
width: imageSize,
height: imageSize,
marginBottom: Spacing.xSmall,
},
headerText: {
...Typography.header.x60,
marginBottom: Spacing.small,
},
bodyText: {
...Typography.body.x30,
marginBottom: Spacing.medium,
},
button: {
...Buttons.primary.base,
marginBottom: Spacing.small,
},
buttonText: {
...Typography.button.primary,
marginRight: Spacing.small,
},
secondaryButton: {
...Buttons.secondary.leftIcon,
},
secondaryButtonIconContainer: {
...Buttons.circle.base,
},
secondaryButtonText: {
...Typography.button.secondaryLeftIcon,
},
})

export default Start
6 changes: 5 additions & 1 deletion src/Home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,11 @@ const SimpleVerificationFlowButton: FunctionComponent = () => {

const EscrowVerificationFlowButton: FunctionComponent = () => {
const { t } = useTranslation()
const handleOnPressReportTestResult = () => {}
const navigation = useNavigation()

const handleOnPressReportTestResult = () => {
navigation.navigate(HomeStackScreens.EscrowVerificationStack)
}

const handleOnPressMoreInfo = () => {}
const descriptionText = t(
Expand Down
8 changes: 8 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@
"reload": "Reload",
"title": "Unknown Error"
},
"escrow_verification": {
"person_and_health_expert": "A person talking to a health expert",
"start": {
"header": "Report a positive test",
"body": "If you have tested positive for COVID-19 (not through an antibody test), you can anonymously report the test.\n\nReporting your test will help others in your community contain the spread of the virus.",
"what_is_a_verification_code": "What is a verification code?"
}
},
"export": {
"code": "Code",
"code_input_body_bluetooth": "Enter your verification code",
Expand Down
37 changes: 37 additions & 0 deletions src/navigation/EscrowVerification.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { FunctionComponent } from "react"
import { createStackNavigator } from "@react-navigation/stack"

import { EscrowVerificationProvider } from "../EscrowVerification/EscrowVerificationContext"
import Start from "../EscrowVerification/Start"

import { EscrowVerificationRoutes } from "."
import { applyHeaderLeftBackButton } from "./HeaderLeftBackButton"

import { Headers } from "../styles"

export type EscrowVerificationRouteParamList = {
EscrowVerificationStart: undefined
}

const Stack = createStackNavigator<EscrowVerificationRouteParamList>()

const AffectedUserStack: FunctionComponent = () => {
return (
<EscrowVerificationProvider>
<Stack.Navigator
screenOptions={{ headerShown: false, gestureEnabled: false }}
>
<Stack.Screen
name={EscrowVerificationRoutes.EscrowVerificationStart}
component={Start}
options={{
...Headers.headerMinimalOptions,
headerLeft: applyHeaderLeftBackButton(),
}}
/>
</Stack.Navigator>
</EscrowVerificationProvider>
)
}

export default AffectedUserStack
6 changes: 6 additions & 0 deletions src/navigation/MainNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import AgeVerification from "../modals/AgeVerification"
import LanguageSelection from "../modals/LanguageSelection"
import ProtectPrivacy from "../modals/ProtectPrivacy"
import AffectedUserStack from "./AffectedUserFlowStack"
import EscrowVerificationStack from "./EscrowVerification"
import SelfAssessmentStack from "./SelfAssessmentStack"
import ExposureDetectionStatusScreen from "../Home/ExposureDetectionStatus/Screen"
import BluetoothInfo from "../Home/BluetoothInfo"
Expand Down Expand Up @@ -169,6 +170,11 @@ const MainNavigator: FunctionComponent = () => {
component={AffectedUserStack}
options={{ gestureEnabled: false }}
/>
<Stack.Screen
name={Stacks.EscrowVerificationStack}
component={EscrowVerificationStack}
options={{ gestureEnabled: false }}
/>
<Stack.Screen name={ModalStackScreens.HowItWorksReviewFromSettings}>
{(props) => <HowItWorksStack {...props} mountLocation="Settings" />}
</Stack.Screen>
Expand Down
19 changes: 15 additions & 4 deletions src/navigation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export type HomeStackScreen =
| "AffectedUserStack"
| "BluetoothInfo"
| "CovidDataDashboard"
| "EscrowVerificationStack"
| "ExposureDetectionStatus"
| "ExposureNotificationsInfo"
| "Home"
Expand All @@ -47,12 +48,11 @@ export type HomeStackScreen =
| "EmergencyRecommendation"
| "CovidRecommendation"

export const HomeStackScreens: {
[key in HomeStackScreen]: HomeStackScreen
} = {
export const HomeStackScreens: Record<HomeStackScreen, HomeStackScreen> = {
AffectedUserStack: "AffectedUserStack",
BluetoothInfo: "BluetoothInfo",
CovidDataDashboard: "CovidDataDashboard",
EscrowVerificationStack: "EscrowVerificationStack",
ExposureDetectionStatus: "ExposureDetectionStatus",
ExposureNotificationsInfo: "ExposureNotificationsInfo",
Home: "Home",
Expand Down Expand Up @@ -186,6 +186,15 @@ export const AffectedUserFlowStackScreens: {
AffectedUserComplete: "AffectedUserComplete",
}

export type EscrowVerificationRoute = "EscrowVerificationStart"

export const EscrowVerificationRoutes: Record<
EscrowVerificationRoute,
EscrowVerificationRoute
> = {
EscrowVerificationStart: "EscrowVerificationStart",
}

export type WelcomeStackScreen = "Welcome"

export const WelcomeStackScreens: {
Expand Down Expand Up @@ -236,17 +245,19 @@ export type Stack =
| "Activation"
| "AffectedUserStack"
| "Connect"
| "EscrowVerificationStack"
| "ExposureHistoryFlow"
| "HowItWorks"
| "Settings"
| "Home"
| "SymptomHistory"

export const Stacks: { [key in Stack]: Stack } = {
export const Stacks: Record<Stack, Stack> = {
Activation: "Activation",
AffectedUserStack: "AffectedUserStack",
Connect: "Connect",
ExposureHistoryFlow: "ExposureHistoryFlow",
EscrowVerificationStack: "EscrowVerificationStack",
HowItWorks: "HowItWorks",
Settings: "Settings",
Home: "Home",
Expand Down

0 comments on commit 7d57b15

Please sign in to comment.