From 513230ef080913caf2ce5fc10aafee7822322d71 Mon Sep 17 00:00:00 2001 From: Radek Czemerys Date: Sat, 3 Oct 2020 21:02:20 +0200 Subject: [PATCH] feature: single validation challenges --- src/lib/NavigationService.ts | 8 +- src/lib/application.ts | 4 +- src/screens/Authenticate/Authenticate.tsx | 92 +++++++++++++++-------- 3 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/lib/NavigationService.ts b/src/lib/NavigationService.ts index ee75c7bf..cba3bebb 100644 --- a/src/lib/NavigationService.ts +++ b/src/lib/NavigationService.ts @@ -1,4 +1,4 @@ -import { NavigationContainerRef } from '@react-navigation/native'; +import { NavigationContainerRef, StackActions } from '@react-navigation/native'; import * as React from 'react'; export const navigationRef = React.createRef(); @@ -7,6 +7,12 @@ export function navigate(name: string, params?: any) { navigationRef.current?.navigate(name, params); } +export function push(name: string, params?: any) { + const pushAction = StackActions.push(name, params); + + navigationRef.current?.dispatch(pushAction); +} + export function goBack() { navigationRef.current?.goBack(); } diff --git a/src/lib/application.ts b/src/lib/application.ts index 7b1b7f61..91be4e46 100644 --- a/src/lib/application.ts +++ b/src/lib/application.ts @@ -17,7 +17,7 @@ import ComponentManager from './ComponentManager'; import { EditorGroup } from './EditorGroup'; import { InstallationService } from './InstallationService'; import { MobileDeviceInterface } from './interface'; -import { navigate } from './NavigationService'; +import { push } from './NavigationService'; import { PreferencesManager } from './PreferencesManager'; import { ReviewService } from './reviewService'; import { SNReactNativeCrypto } from './SNReactNativeCrypto'; @@ -76,7 +76,7 @@ export class MobileApplication extends SNApplication { } promptForChallenge(challenge: Challenge) { - navigate(SCREEN_AUTHENTICATE, { challenge, title: challenge.modalTitle }); + push(SCREEN_AUTHENTICATE, { challenge, title: challenge.modalTitle }); } setMobileServices(services: MobileServices) { diff --git a/src/screens/Authenticate/Authenticate.tsx b/src/screens/Authenticate/Authenticate.tsx index e6dccb4c..1194af35 100644 --- a/src/screens/Authenticate/Authenticate.tsx +++ b/src/screens/Authenticate/Authenticate.tsx @@ -64,6 +64,9 @@ export const Authenticate = ({ const [keyboardType, setKeyboardType] = useState< PasscodeKeyboardType | undefined >(undefined); + const [singleValidation] = useState( + () => !(challenge.prompts.filter(prompt => prompt.validates).length > 0) + ); const [{ challengeValues, challengeValueStates }, dispatch] = useReducer( authenticationReducer, { @@ -114,24 +117,32 @@ export const Authenticate = ({ const validateChallengeValue = useCallback( async (challengeValue: ChallengeValue) => { - const state = challengeValueStates[challengeValue.prompt.id]; + if (singleValidation) { + return application?.submitValuesForChallenge( + challenge, + Object.values(challengeValues) + ); + } else { + const state = challengeValueStates[challengeValue.prompt.id]; - if ( - state === AuthenticationValueStateType.Locked || - state === AuthenticationValueStateType.Success - ) { - return; + if ( + state === AuthenticationValueStateType.Locked || + state === AuthenticationValueStateType.Success + ) { + return; + } + return application?.submitValuesForChallenge(challenge, [ + challengeValue, + ]); } - - dispatch({ - type: 'setState', - id: challengeValue.prompt.id.toString(), - state: AuthenticationValueStateType.Pending, - }); - - await application?.submitValuesForChallenge(challenge, [challengeValue]); }, - [challengeValueStates, application, challenge] + [ + challengeValueStates, + singleValidation, + challengeValues, + application, + challenge, + ] ); const onValueLocked = useCallback((challengeValue: ChallengeValue) => { @@ -454,17 +465,21 @@ export const Authenticate = ({ const onSubmitPress = () => { const challengeValue = challengeValues[firstNotSuccessful!]; - const state = challengeValueStates[firstNotSuccessful!]; - if ( - challengeValue.prompt.validation === ChallengeValidation.Biometric && - (state === AuthenticationValueStateType.Locked || - state === AuthenticationValueStateType.Fail) - ) { - beginAuthenticatingForNextChallengeReason(); - return; - } + if (singleValidation) { + validateChallengeValue(challengeValue); + } else { + const state = challengeValueStates[firstNotSuccessful!]; + if ( + challengeValue.prompt.validation === ChallengeValidation.Biometric && + (state === AuthenticationValueStateType.Locked || + state === AuthenticationValueStateType.Fail) + ) { + beginAuthenticatingForNextChallengeReason(); + return; + } - validateChallengeValue(challengeValue); + validateChallengeValue(challengeValue); + } }; const switchKeyboard = () => { @@ -475,6 +490,14 @@ export const Authenticate = ({ } }; + const readyToSubmit = useMemo( + () => + Object.values(challengeValues) + .map(challengeValue => challengeValue.value) + .filter(value => !value).length === 0, + [challengeValues] + ); + const renderAuthenticationSource = ( challengeValue: ChallengeValue, index: number @@ -541,9 +564,13 @@ export const Authenticate = ({ keyboardType={keyboardType} keyboardAppearance={styleKit?.keyboardColorForActiveTheme()} underlineColorAndroid={'transparent'} - onSubmitEditing={() => { - validateChallengeValue(challengeValue); - }} + onSubmitEditing={ + !singleValidation + ? () => { + validateChallengeValue(challengeValue); + } + : undefined + } /> @@ -588,11 +615,12 @@ export const Authenticate = ({ )}