feature: single validation challenges

This commit is contained in:
Radek Czemerys
2020-10-03 21:02:20 +02:00
parent fe60886c2b
commit 513230ef08
3 changed files with 69 additions and 35 deletions

View File

@@ -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<NavigationContainerRef>();
@@ -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();
}

View File

@@ -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) {

View File

@@ -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
}
/>
</SectionedTableCell>
</SectionContainer>
@@ -588,11 +615,12 @@ export const Authenticate = ({
)}
<ButtonCell
maxHeight={45}
disabled={isPending}
disabled={singleValidation ? !readyToSubmit : isPending}
title={
!!firstNotSuccessful &&
findIndexInObject(challengeValueStates, firstNotSuccessful) ===
Object.keys(challengeValueStates).length - 1
singleValidation ||
(!!firstNotSuccessful &&
findIndexInObject(challengeValueStates, firstNotSuccessful) ===
Object.keys(challengeValueStates).length - 1)
? 'Submit'
: 'Next'
}