Refactor password error in request pop up and remember checkbox (#503)

* error and remember checkbox refactoring

* make it build

* remove margin

Co-authored-by: Github Actions <action@github.com>
This commit is contained in:
Thibaut Sardan 2020-10-20 16:34:48 +02:00 committed by GitHub
parent 0c4c3365be
commit 34e16c2a04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 65 deletions

View File

@ -47,6 +47,7 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
const [isBusy, setIsBusy] = useState(false);
const [isLocked, setIsLocked] = useState<boolean | null>(null);
const [savePass, setSavePass] = useState(false);
const [password, setPassword] = useState('');
useEffect(() => {
setIsLocked(null);
@ -58,6 +59,10 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
timeout = setTimeout(() => {
setIsLocked(true);
}, remainingTime);
// if the account was unlocked check the remember me
// automatically to prolong the unlock period
!isLocked && setSavePass(true);
})
.catch((error: Error) => console.error(error));
@ -90,7 +95,7 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
);
const _onSign = useCallback(
(password?: string): Promise<void> => {
(): Promise<void> => {
setIsBusy(true);
return approveSignPassword(signId, savePass, password)
@ -104,12 +109,7 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
console.error(error);
});
},
[onAction, savePass, signId]
);
const _onSignQuick = useCallback(
() => _onSign(),
[_onSign]
[onAction, password, savePass, signId]
);
const _onSignature = useCallback(
@ -123,33 +123,45 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
[onAction, signId]
);
const SignButton = () => isLocked
? (
<Unlock
buttonText={buttonText}
error={error}
isBusy={isBusy}
onSign={_onSign}
>
<Checkbox
checked={savePass}
label={t<string>(
"Don't ask me again for the next {{expiration}} minutes",
{ replace: { expiration: PASSWORD_EXPIRY_MIN } }
)}
onChange={setSavePass}
const RememberPasswordCheckbox = () => (
<Checkbox
checked={savePass}
label={ isLocked
? t<string>(
'Remember my password for the next {{expiration}} minutes',
{ replace: { expiration: PASSWORD_EXPIRY_MIN } }
)
: t<string>(
'Extend the period without password by {{expiration}} minutes',
{ replace: { expiration: PASSWORD_EXPIRY_MIN } }
)
}
onChange={setSavePass}
/>
);
const SignButton = () => (
<>
{ isLocked && (
<Unlock
error={error}
isBusy={isBusy}
onSign={_onSign}
password={password}
setError={setError}
setPassword={setPassword}
/>
</Unlock>
)
: (
)}
<RememberPasswordCheckbox />
<Button
isBusy={isBusy}
isDisabled={isLocked === null}
onClick={_onSignQuick}
isDisabled={(!!isLocked && !password) || !!error}
onClick={_onSign}
>
{buttonText}
</Button>
);
</>
);
if (payload !== null) {
const json = request.payload as SignerPayloadJSON;
@ -180,7 +192,9 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
)
}
<SignArea>
{isFirst && !isExternal && <SignButton/>}
{isFirst && !isExternal && (
<SignButton/>
)}
<CancelButton>
<Link
isDanger

View File

@ -1,64 +1,57 @@
// Copyright 2019-2020 @polkadot/extension-ui authors & contributors
// SPDX-License-Identifier: Apache-2.0
import React, { useCallback, useEffect, useState } from 'react';
import { ThemeProps } from '@polkadot/extension-ui/types';
import { Button, InputWithLabel } from '../../components';
import React, { useCallback } from 'react';
import styled from 'styled-components';
import { InputWithLabel } from '../../components';
import useTranslation from '../../hooks/useTranslation';
interface Props {
buttonText: string;
children?: React.ReactNode;
interface Props extends ThemeProps {
className?: string;
error?: string | null;
isBusy: boolean;
onSign: (password: string) => Promise<void>;
onSign: () => Promise<void>;
password: string;
setError: (error: string | null) => void;
setPassword: (password: string) => void;
}
function Unlock ({ buttonText, children, className, error, isBusy, onSign }: Props): React.ReactElement<Props> {
function Unlock ({ className, error, isBusy, onSign, password, setError, setPassword }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [ownError, setError] = useState<string | null>();
const [password, setPassword] = useState('');
useEffect((): void => {
setError(error || null);
}, [error]);
const _onChangePassword = useCallback(
(password: string): void => {
setPassword(password);
setError(null);
},
[]
);
const _onClick = useCallback(
() => onSign(password),
[onSign, password]
[setError, setPassword]
);
return (
<div className={className}>
<InputWithLabel
disabled={isBusy}
isError={!password || !!ownError}
isError={!password || !!error}
isFocused
label={t<string>('Password for this account')}
onChange={_onChangePassword}
onEnter={_onClick}
onEnter={onSign}
type='password'
withoutMargin={!!children}
value={password}
withoutMargin={true}
/>
{children}
<Button
isBusy={isBusy}
isDisabled={!password}
onClick={_onClick}
>
{buttonText}
</Button>
{error && <div className='error'>{error}</div>}
</div>
);
}
export default React.memo(Unlock);
export default React.memo(styled(Unlock)(({ theme }: ThemeProps) => `
.error {
font-size: ${theme.labelFontSize};
line-height: ${theme.labelLineHeight};
color: ${theme.errorColor};
}
`));

View File

@ -24,7 +24,7 @@ interface Props {
withoutMargin?: boolean;
}
function InputWithLabel ({ className, defaultValue, disabled, isError, isFocused, isReadOnly, label, onBlur, onChange, onEnter, placeholder, type = 'text', value }: Props): React.ReactElement<Props> {
function InputWithLabel ({ className, defaultValue, disabled, isError, isFocused, isReadOnly, label = '', onBlur, onChange, onEnter, placeholder, type = 'text', value, withoutMargin }: Props): React.ReactElement<Props> {
const _checkEnter = useCallback(
(event: React.KeyboardEvent<HTMLInputElement>): void => {
onEnter && event.key === 'Enter' && onEnter();
@ -41,7 +41,7 @@ function InputWithLabel ({ className, defaultValue, disabled, isError, isFocused
return (
<Label
className={className}
className={`${className || ''} ${withoutMargin ? 'withoutMargin' : ''}`}
label={label}
>
<Input
@ -64,6 +64,10 @@ function InputWithLabel ({ className, defaultValue, disabled, isError, isFocused
);
}
export default styled(InputWithLabel)(({ withoutMargin }: Props) => `
margin-bottom: ${withoutMargin ? 0 : 16}px;
`);
export default styled(InputWithLabel)`
margin-bottom: 16px;
&.withoutMargin {
margin-bottom: 0px;
}
`;