@@ -2,13 +2,16 @@ import {useFocusEffect} from '@react-navigation/native';
2
2
import lodashIsEqual from 'lodash/isEqual' ;
3
3
import type { ForwardedRef , MutableRefObject , ReactNode , RefAttributes } from 'react' ;
4
4
import React , { createRef , forwardRef , useCallback , useEffect , useImperativeHandle , useMemo , useRef , useState } from 'react' ;
5
+ import { InteractionManager } from 'react-native' ;
5
6
import type { NativeSyntheticEvent , StyleProp , TextInputSubmitEditingEventData , ViewStyle } from 'react-native' ;
6
7
import { useOnyx } from 'react-native-onyx' ;
8
+ import { useInputBlurContext } from '@components/InputBlurContext' ;
7
9
import useDebounceNonReactive from '@hooks/useDebounceNonReactive' ;
8
10
import useLocalize from '@hooks/useLocalize' ;
9
- import * as ValidationUtils from '@libs/ValidationUtils' ;
11
+ import { isSafari } from '@libs/Browser' ;
12
+ import { prepareValues } from '@libs/ValidationUtils' ;
10
13
import Visibility from '@libs/Visibility' ;
11
- import * as FormActions from '@userActions/FormActions' ;
14
+ import { clearErrorFields , clearErrors , setDraftValues , setErrors as setFormErrors } from '@userActions/FormActions' ;
12
15
import CONST from '@src/CONST' ;
13
16
import type { OnyxFormDraftKey , OnyxFormKey } from '@src/ONYXKEYS' ;
14
17
import ONYXKEYS from '@src/ONYXKEYS' ;
@@ -95,15 +98,16 @@ function FormProvider(
95
98
const [ inputValues , setInputValues ] = useState < Form > ( ( ) => ( { ...draftValues } ) ) ;
96
99
const [ errors , setErrors ] = useState < GenericFormInputErrors > ( { } ) ;
97
100
const hasServerError = useMemo ( ( ) => ! ! formState && ! isEmptyObject ( formState ?. errors ) , [ formState ] ) ;
101
+ const { setIsBlurred} = useInputBlurContext ( ) ;
98
102
99
103
const onValidate = useCallback (
100
104
( values : FormOnyxValues , shouldClearServerError = true ) => {
101
- const trimmedStringValues = shouldTrimValues ? ValidationUtils . prepareValues ( values ) : values ;
105
+ const trimmedStringValues = shouldTrimValues ? prepareValues ( values ) : values ;
102
106
103
107
if ( shouldClearServerError ) {
104
- FormActions . clearErrors ( formID ) ;
108
+ clearErrors ( formID ) ;
105
109
}
106
- FormActions . clearErrorFields ( formID ) ;
110
+ clearErrorFields ( formID ) ;
107
111
108
112
const validateErrors : GenericFormInputErrors = validate ?.( trimmedStringValues ) ?? { } ;
109
113
@@ -168,7 +172,7 @@ function FormProvider(
168
172
}
169
173
170
174
// Prepare validation values
171
- const trimmedStringValues = shouldTrimValues ? ValidationUtils . prepareValues ( inputValues ) : inputValues ;
175
+ const trimmedStringValues = shouldTrimValues ? prepareValues ( inputValues ) : inputValues ;
172
176
173
177
// Validate in order to make sure the correct error translations are displayed,
174
178
// making sure to not clear server errors if they exist
@@ -194,7 +198,7 @@ function FormProvider(
194
198
}
195
199
196
200
// Prepare values before submitting
197
- const trimmedStringValues = shouldTrimValues ? ValidationUtils . prepareValues ( inputValues ) : inputValues ;
201
+ const trimmedStringValues = shouldTrimValues ? prepareValues ( inputValues ) : inputValues ;
198
202
199
203
// Touches all form inputs, so we can validate the entire form
200
204
Object . keys ( inputRefs . current ) . forEach ( ( inputID ) => ( touchedInputs . current [ inputID ] = true ) ) ;
@@ -246,16 +250,16 @@ function FormProvider(
246
250
) ;
247
251
248
252
const resetErrors = useCallback ( ( ) => {
249
- FormActions . clearErrors ( formID ) ;
250
- FormActions . clearErrorFields ( formID ) ;
253
+ clearErrors ( formID ) ;
254
+ clearErrorFields ( formID ) ;
251
255
setErrors ( { } ) ;
252
256
} , [ formID ] ) ;
253
257
254
258
const resetFormFieldError = useCallback (
255
259
( inputID : keyof Form ) => {
256
260
const newErrors = { ...errors } ;
257
261
delete newErrors [ inputID ] ;
258
- FormActions . setErrors ( formID , newErrors as Errors ) ;
262
+ setFormErrors ( formID , newErrors as Errors ) ;
259
263
setErrors ( newErrors ) ;
260
264
} ,
261
265
[ errors , formID ] ,
@@ -371,6 +375,11 @@ function FormProvider(
371
375
} , VALIDATE_DELAY ) ;
372
376
}
373
377
inputProps . onBlur ?.( event ) ;
378
+ if ( isSafari ( ) ) {
379
+ InteractionManager . runAfterInteractions ( ( ) => {
380
+ setIsBlurred ( true ) ;
381
+ } ) ;
382
+ }
374
383
} ,
375
384
onInputChange : ( value , key ) => {
376
385
const inputKey = key ?? inputID ;
@@ -387,13 +396,13 @@ function FormProvider(
387
396
} ) ;
388
397
389
398
if ( inputProps . shouldSaveDraft && ! formID . includes ( 'Draft' ) ) {
390
- FormActions . setDraftValues ( formID , { [ inputKey ] : value } ) ;
399
+ setDraftValues ( formID , { [ inputKey ] : value } ) ;
391
400
}
392
401
inputProps . onValueChange ?.( value , inputKey ) ;
393
402
} ,
394
403
} ;
395
404
} ,
396
- [ draftValues , inputValues , formState ?. errorFields , errors , submit , setTouchedInput , shouldValidateOnBlur , onValidate , hasServerError , formID , shouldValidateOnChange ] ,
405
+ [ draftValues , inputValues , formState ?. errorFields , errors , submit , setTouchedInput , shouldValidateOnBlur , onValidate , hasServerError , setIsBlurred , formID , shouldValidateOnChange ] ,
397
406
) ;
398
407
const value = useMemo ( ( ) => ( { registerInput} ) , [ registerInput ] ) ;
399
408
0 commit comments