mirror of
https://github.com/standardnotes/mobile.git
synced 2026-05-19 12:04:31 -04:00
feature: single validation challenges
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user