Skip to content

Commit

Permalink
Reset input value on unlock
Browse files Browse the repository at this point in the history
  • Loading branch information
heathsnee committed Jul 19, 2024
1 parent c387a63 commit f007b3c
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 74 deletions.
13 changes: 8 additions & 5 deletions apps/extension/src/components/layout/unlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ interface IProps {
export const Unlock: React.FC<IProps & BoxProps> = ({ isUnlocked, isLoading, onUnlock, className, ...rest }) => {
const intl = useIntl()
const navigate = useNavigate()
const inputRef = useRef(null)
const inputRef = useRef<HTMLInputElement>()
const client = useMessageClient()

const { keystore, keystores, selectKeystore } = useSharedStore(state => ({
Expand All @@ -71,7 +71,6 @@ export const Unlock: React.FC<IProps & BoxProps> = ({ isUnlocked, isLoading, onU
selectKeystore: state.selectKeystoreAction,
}))

const [previous, setPrevious] = useState<boolean | null>(null)
const [error, setError] = useState<string>('')

useEffect(() => {
Expand All @@ -87,22 +86,26 @@ export const Unlock: React.FC<IProps & BoxProps> = ({ isUnlocked, isLoading, onU
// eslint-disable-next-line no-console
console.error(err)
setError(intl.formatMessage(messages.unlock_error))
} finally {
if (inputRef?.current) {
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set
nativeInputValueSetter.call(inputRef.current, '')
const event = new Event('input', { bubbles: true })
inputRef.current.dispatchEvent(event)
}
}
}

const handleWebAuthN = () => {
if (!keystore?.webAuthn) return
if (isLoading === true) return
if (isUnlocked === true) return
if (previous === true) return
setPrevious(isUnlocked)
// eslint-disable-next-line no-console
login(keystore).then(handleUnlock).catch(console.error)
}

useEffect(() => {
handleWebAuthN()
setPrevious(isUnlocked)
}, [keystore?.id, isLoading, isUnlocked])

const selectItems = useMemo(() => {
Expand Down
136 changes: 67 additions & 69 deletions packages/ui/src/components/form/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import set from 'lodash/set'
import unset from 'lodash/unset'
import type { FormEvent, PropsWithChildren } from 'react'
import React, { useEffect, useMemo } from 'react'
import React, { forwardRef, useEffect, useMemo } from 'react'
import { defineMessages, useIntl } from 'react-intl'
import { useImmer } from 'use-immer'

Expand Down Expand Up @@ -44,80 +44,78 @@ const rootFieldCtx = {

const emptyErrors = {}

export const Form: React.FC<PropsWithChildren<Props>> = ({
children,
initialValues,
errors = emptyErrors,
onSubmit,
onChange,
...rest
}) => {
const intl = useIntl()
const [state, setState] = useImmer<State<Props['initialValues']>>({
error: '',
isLoading: false,
values: initialValues,
})

useEffect(() => {
setState(draft => {
draft.values = initialValues
export const Form = forwardRef<HTMLFormElement, PropsWithChildren<Props>>(
({ children, initialValues, errors = emptyErrors, onSubmit, onChange, ...rest }, ref) => {
const intl = useIntl()
const [state, setState] = useImmer<State<Props['initialValues']>>({
error: '',
isLoading: false,
values: initialValues,
})
}, [initialValues])

useEffect(() => {
if (onChange) onChange(state.values)
}, [state.values])
useEffect(() => {
setState(draft => {
draft.values = initialValues
})
}, [initialValues])

const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
setState(draft => {
draft.isLoading = true
})
useEffect(() => {
if (onChange) onChange(state.values)
}, [state.values])

const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault()
setState(draft => {
draft.isLoading = true
})

if (onSubmit)
onSubmit(state.values)
.catch(error => {
// eslint-disable-next-line no-console
console.error(error)
setState(draft => {
draft.error = intl.formatMessage(messages.error, { hasMessage: !!error?.message, message: error?.message })
if (onSubmit)
onSubmit(state.values)
.catch(error => {
// eslint-disable-next-line no-console
console.error(error)
setState(draft => {
draft.error = intl.formatMessage(messages.error, {
hasMessage: !!error?.message,
message: error?.message,
})
})
})
})
.finally(() => {
setState(draft => {
draft.isLoading = false
.finally(() => {
setState(draft => {
draft.isLoading = false
})
})
})
}
}

const handleFieldChange = (name: string, value?: any) => {
setState(draft => {
const { values } = draft
if (value === null) {
unset(values, name)
draft.values = values
} else {
draft.values = set({ ...values }, name, value)
}
})
}
const handleFieldChange = (name: string, value?: any) => {
setState(draft => {
const { values } = draft
if (value === null) {
unset(values, name)
draft.values = values
} else {
draft.values = set({ ...values }, name, value)
}
})
}

const formCtx = useMemo(
() => ({
...state,
errors,
onFieldChange: handleFieldChange,
}),
[state.isLoading, state.values, errors],
)
const formCtx = useMemo(
() => ({
...state,
errors,
onFieldChange: handleFieldChange,
}),
[state.isLoading, state.values, errors],
)

return (
<Box {...rest} component="form" onSubmit={handleSubmit}>
<ValidationErrorMessage message={state.error} />
<FormContext.Provider value={formCtx}>
<FieldContext.Provider value={rootFieldCtx}>{children}</FieldContext.Provider>
</FormContext.Provider>
</Box>
)
}
return (
<Box {...rest} component="form" onSubmit={handleSubmit} ref={ref}>
<ValidationErrorMessage message={state.error} />
<FormContext.Provider value={formCtx}>
<FieldContext.Provider value={rootFieldCtx}>{children}</FieldContext.Provider>
</FormContext.Provider>
</Box>
)
},
)

0 comments on commit f007b3c

Please sign in to comment.