Merge pull request #625 from ente-io/message-dialog-redesign-v4
Message dialog redesign v4
This commit is contained in:
commit
857813db21
|
@ -1,9 +1,10 @@
|
|||
import React from 'react';
|
||||
import constants from 'utils/strings/constants';
|
||||
import DialogBox from 'components/DialogBox';
|
||||
import SingleInputForm, {
|
||||
SingleInputFormProps,
|
||||
} from 'components/SingleInputForm';
|
||||
import DialogBoxBase from 'components/DialogBox/base';
|
||||
import { DialogContent, DialogTitle } from '@mui/material';
|
||||
|
||||
export interface CollectionNamerAttributes {
|
||||
callback: (name: string) => void;
|
||||
|
@ -39,19 +40,19 @@ export default function CollectionNamer({ attributes, ...props }: Props) {
|
|||
};
|
||||
|
||||
return (
|
||||
<DialogBox
|
||||
open={props.show}
|
||||
attributes={{ title: attributes.title }}
|
||||
onClose={props.onHide}
|
||||
titleCloseButton
|
||||
maxWidth="xs">
|
||||
<SingleInputForm
|
||||
callback={onSubmit}
|
||||
fieldType="text"
|
||||
buttonText={attributes.buttonText}
|
||||
placeholder={constants.ENTER_ALBUM_NAME}
|
||||
initialValue={attributes.autoFilledName}
|
||||
/>
|
||||
</DialogBox>
|
||||
<DialogBoxBase open={props.show} onClose={props.onHide}>
|
||||
<DialogTitle>{attributes.title}</DialogTitle>
|
||||
<DialogContent>
|
||||
<SingleInputForm
|
||||
callback={onSubmit}
|
||||
fieldType="text"
|
||||
buttonText={attributes.buttonText}
|
||||
placeholder={constants.ENTER_ALBUM_NAME}
|
||||
initialValue={attributes.autoFilledName}
|
||||
submitButtonProps={{ sx: { mt: 1, mb: 2 } }}
|
||||
secondaryButtonAction={props.onHide}
|
||||
/>
|
||||
</DialogContent>
|
||||
</DialogBoxBase>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ const CollectionOptions = (props: CollectionOptionsProps) => {
|
|||
close: { variant: 'danger' },
|
||||
});
|
||||
} finally {
|
||||
syncWithRemote();
|
||||
syncWithRemote(false, true);
|
||||
loader && finishLoading();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -8,7 +8,6 @@ import { handleSharingErrors } from 'utils/error';
|
|||
import { getData, LS_KEYS } from 'utils/storage/localStorage';
|
||||
import constants from 'utils/strings/constants';
|
||||
import { CollectionShareSharees } from './sharees';
|
||||
import CollectionShareSubmitButton from './submitButton';
|
||||
export default function EmailShare({ collection }) {
|
||||
const galleryContext = useContext(GalleryContext);
|
||||
|
||||
|
@ -38,7 +37,10 @@ export default function EmailShare({ collection }) {
|
|||
placeholder={constants.ENTER_EMAIL}
|
||||
fieldType="email"
|
||||
buttonText={constants.SHARE}
|
||||
customSubmitButton={CollectionShareSubmitButton}
|
||||
submitButtonProps={{
|
||||
size: 'medium',
|
||||
sx: { mt: 1, mb: 2 },
|
||||
}}
|
||||
/>
|
||||
<CollectionShareSharees collection={collection} />
|
||||
</>
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
import DialogBox from 'components/DialogBox';
|
||||
import { DialogContent, DialogTitle, styled } from '@mui/material';
|
||||
import DialogBoxBase from 'components/DialogBox/base';
|
||||
import SingleInputForm from 'components/SingleInputForm';
|
||||
import React from 'react';
|
||||
import CryptoWorker from 'utils/crypto';
|
||||
import constants from 'utils/strings/constants';
|
||||
|
||||
const SetPublicLinkSetPasswordDialog = styled(DialogBoxBase)(({ theme }) => ({
|
||||
'& .MuiDialog-container': {
|
||||
justifyContent: 'flex-end',
|
||||
},
|
||||
'& .MuiDialog-paper': {
|
||||
marginRight: theme.spacing(9),
|
||||
},
|
||||
}));
|
||||
|
||||
export function PublicLinkSetPassword({
|
||||
open,
|
||||
onClose,
|
||||
|
@ -35,20 +46,18 @@ export function PublicLinkSetPassword({
|
|||
});
|
||||
};
|
||||
return (
|
||||
<DialogBox
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
PaperProps={{ sx: { maxWidth: '350px' } }}
|
||||
titleCloseButton
|
||||
attributes={{
|
||||
title: constants.PASSWORD_LOCK,
|
||||
}}>
|
||||
<SingleInputForm
|
||||
callback={savePassword}
|
||||
placeholder={constants.RETURN_PASSPHRASE_HINT}
|
||||
buttonText={constants.LOCK}
|
||||
fieldType="password"
|
||||
/>
|
||||
</DialogBox>
|
||||
<SetPublicLinkSetPasswordDialog open={open} onClose={onClose}>
|
||||
<DialogTitle>{constants.PASSWORD_LOCK}</DialogTitle>
|
||||
<DialogContent>
|
||||
<SingleInputForm
|
||||
callback={savePassword}
|
||||
placeholder={constants.RETURN_PASSPHRASE_HINT}
|
||||
buttonText={constants.LOCK}
|
||||
fieldType="password"
|
||||
secondaryButtonAction={onClose}
|
||||
submitButtonProps={{ sx: { mt: 1, mb: 2 } }}
|
||||
/>
|
||||
</DialogContent>
|
||||
</SetPublicLinkSetPasswordDialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
import { FlexWrapper } from 'components/Container';
|
||||
import SubmitButton, { SubmitButtonProps } from 'components/SubmitButton';
|
||||
import React from 'react';
|
||||
export default function CollectionShareSubmitButton(props: SubmitButtonProps) {
|
||||
return (
|
||||
<FlexWrapper style={{ justifyContent: 'flex-end' }}>
|
||||
<SubmitButton {...props} size="medium" inline sx={{ my: 2 }} />
|
||||
</FlexWrapper>
|
||||
);
|
||||
}
|
|
@ -6,6 +6,7 @@ import SubmitButton from './SubmitButton';
|
|||
import TextField from '@mui/material/TextField';
|
||||
import ShowHidePassword from './Form/ShowHidePassword';
|
||||
import { FlexWrapper } from './Container';
|
||||
import { Button } from '@mui/material';
|
||||
|
||||
interface formValues {
|
||||
inputValue: string;
|
||||
|
@ -18,11 +19,15 @@ export interface SingleInputFormProps {
|
|||
fieldType: 'text' | 'email' | 'password';
|
||||
placeholder: string;
|
||||
buttonText: string;
|
||||
customSubmitButton?: any;
|
||||
submitButtonProps?: any;
|
||||
initialValue?: string;
|
||||
secondaryButtonAction?: () => void;
|
||||
}
|
||||
|
||||
export default function SingleInputForm(props: SingleInputFormProps) {
|
||||
const { submitButtonProps } = props;
|
||||
const { sx: buttonSx, ...restSubmitButtonProps } = submitButtonProps ?? {};
|
||||
|
||||
const [loading, SetLoading] = useState(false);
|
||||
const [showPassword, setShowPassword] = useState(false);
|
||||
|
||||
|
@ -100,19 +105,24 @@ export default function SingleInputForm(props: SingleInputFormProps) {
|
|||
),
|
||||
}}
|
||||
/>
|
||||
<FlexWrapper></FlexWrapper>
|
||||
{props.customSubmitButton ? (
|
||||
<props.customSubmitButton
|
||||
buttonText={props.buttonText}
|
||||
loading={loading}
|
||||
/>
|
||||
) : (
|
||||
<FlexWrapper justifyContent={'flex-end'}>
|
||||
{props.secondaryButtonAction && (
|
||||
<Button
|
||||
onClick={props.secondaryButtonAction}
|
||||
size="large"
|
||||
color="secondary"
|
||||
sx={{ mt: 2, mb: 4, mr: 1, ...buttonSx }}
|
||||
{...restSubmitButtonProps}>
|
||||
{constants.CANCEL}
|
||||
</Button>
|
||||
)}
|
||||
<SubmitButton
|
||||
sx={{ mt: 2 }}
|
||||
sx={{ mt: 2, ...buttonSx }}
|
||||
buttonText={props.buttonText}
|
||||
loading={loading}
|
||||
{...restSubmitButtonProps}
|
||||
/>
|
||||
)}
|
||||
</FlexWrapper>
|
||||
</form>
|
||||
)}
|
||||
</Formik>
|
||||
|
|
|
@ -4,13 +4,12 @@ import React, { FC } from 'react';
|
|||
export interface SubmitButtonProps {
|
||||
loading: boolean;
|
||||
buttonText: string;
|
||||
inline?: any;
|
||||
|
||||
disabled?: boolean;
|
||||
}
|
||||
const SubmitButton: FC<ButtonProps<'button', SubmitButtonProps>> = ({
|
||||
loading,
|
||||
buttonText,
|
||||
inline,
|
||||
disabled,
|
||||
sx,
|
||||
...props
|
||||
|
@ -21,7 +20,6 @@ const SubmitButton: FC<ButtonProps<'button', SubmitButtonProps>> = ({
|
|||
variant="contained"
|
||||
color="accent"
|
||||
type="submit"
|
||||
fullWidth={!inline}
|
||||
disabled={loading || disabled}
|
||||
sx={{ my: 4, ...sx }}
|
||||
{...props}>
|
||||
|
|
|
@ -71,12 +71,11 @@ export default function TwoFactorModalManageSection(props: Iprops) {
|
|||
return (
|
||||
<>
|
||||
<Grid
|
||||
mb={2}
|
||||
container
|
||||
mb={1.5}
|
||||
rowSpacing={1}
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
textAlign={'center'}>
|
||||
justifyContent="center">
|
||||
<Grid item sm={9} xs={12}>
|
||||
{constants.UPDATE_TWO_FACTOR_LABEL}
|
||||
</Grid>
|
||||
|
@ -84,17 +83,16 @@ export default function TwoFactorModalManageSection(props: Iprops) {
|
|||
<Button
|
||||
color={'accent'}
|
||||
onClick={warnTwoFactorReconfigure}
|
||||
style={{ width: '100%' }}>
|
||||
size="large">
|
||||
{constants.RECONFIGURE}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid
|
||||
container
|
||||
rowSpacing={1}
|
||||
container
|
||||
alignItems="center"
|
||||
justifyContent="center"
|
||||
textAlign={'center'}>
|
||||
justifyContent="center">
|
||||
<Grid item sm={9} xs={12}>
|
||||
{constants.DISABLE_TWO_FACTOR_LABEL}{' '}
|
||||
</Grid>
|
||||
|
@ -103,7 +101,7 @@ export default function TwoFactorModalManageSection(props: Iprops) {
|
|||
<Button
|
||||
color={'danger'}
|
||||
onClick={warnTwoFactorDisable}
|
||||
style={{ width: '100%' }}>
|
||||
size="large">
|
||||
{constants.DISABLE}
|
||||
</Button>
|
||||
</Grid>
|
||||
|
|
|
@ -3,10 +3,16 @@ import { getTwoFactorStatus } from 'services/userService';
|
|||
import { SetLoading } from 'types/gallery';
|
||||
import { getData, LS_KEYS, setData } from 'utils/storage/localStorage';
|
||||
import constants from 'utils/strings/constants';
|
||||
import DialogBox from '../../DialogBox';
|
||||
import TwoFactorModalSetupSection from './Setup';
|
||||
import TwoFactorModalManageSection from './Manage';
|
||||
import { Dialog, DialogContent, styled } from '@mui/material';
|
||||
import DialogTitleWithCloseButton from 'components/DialogBox/TitleWithCloseButton';
|
||||
|
||||
const TwoFactorDialog = styled(Dialog)(({ theme }) => ({
|
||||
'& .MuiDialogContent-root': {
|
||||
padding: theme.spacing(2, 4),
|
||||
},
|
||||
}));
|
||||
interface Props {
|
||||
show: boolean;
|
||||
onHide: () => void;
|
||||
|
@ -18,18 +24,21 @@ function TwoFactorModal(props: Props) {
|
|||
const [isTwoFactorEnabled, setTwoFactorStatus] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.show) {
|
||||
return;
|
||||
}
|
||||
const isTwoFactorEnabled =
|
||||
getData(LS_KEYS.USER).isTwoFactorEnabled ?? false;
|
||||
setTwoFactorStatus(isTwoFactorEnabled);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.show) {
|
||||
return;
|
||||
}
|
||||
const main = async () => {
|
||||
const isTwoFactorEnabled = await getTwoFactorStatus();
|
||||
setTwoFactorStatus(isTwoFactorEnabled);
|
||||
setData(LS_KEYS.USER, {
|
||||
...getData(LS_KEYS.USER),
|
||||
isTwoFactorEnabled: false,
|
||||
isTwoFactorEnabled,
|
||||
});
|
||||
};
|
||||
main();
|
||||
|
@ -41,22 +50,18 @@ function TwoFactorModal(props: Props) {
|
|||
};
|
||||
|
||||
return (
|
||||
<DialogBox
|
||||
size="xs"
|
||||
fullWidth
|
||||
open={props.show}
|
||||
onClose={props.onHide}
|
||||
attributes={{
|
||||
title: constants.TWO_FACTOR_AUTHENTICATION,
|
||||
}}>
|
||||
<>
|
||||
<TwoFactorDialog maxWidth="xs" open={props.show} onClose={props.onHide}>
|
||||
<DialogTitleWithCloseButton onClose={props.onHide}>
|
||||
{constants.TWO_FACTOR_AUTHENTICATION}
|
||||
</DialogTitleWithCloseButton>
|
||||
<DialogContent sx={{ px: 4 }}>
|
||||
{isTwoFactorEnabled ? (
|
||||
<TwoFactorModalManageSection close={close} />
|
||||
) : (
|
||||
<TwoFactorModalSetupSection close={close} />
|
||||
)}
|
||||
</>
|
||||
</DialogBox>
|
||||
</DialogContent>
|
||||
</TwoFactorDialog>
|
||||
);
|
||||
}
|
||||
export default TwoFactorModal;
|
||||
|
|
|
@ -50,38 +50,43 @@ export default function VerifyTwoFactor(props: Props) {
|
|||
validateOnBlur={false}
|
||||
onSubmit={submitForm}>
|
||||
{({ values, errors, handleChange, handleSubmit, submitForm }) => (
|
||||
<form
|
||||
noValidate
|
||||
onSubmit={handleSubmit}
|
||||
style={{ width: '100%' }}>
|
||||
<Typography mb={2} variant="body2" color="text.secondary">
|
||||
{constants.ENTER_TWO_FACTOR_OTP}
|
||||
</Typography>
|
||||
<Box my={2}>
|
||||
<OtpInput
|
||||
ref={otpInputRef}
|
||||
shouldAutoFocus
|
||||
value={values.otp}
|
||||
onChange={onChange(handleChange('otp'), submitForm)}
|
||||
numInputs={6}
|
||||
separator={'-'}
|
||||
isInputNum
|
||||
className={'otp-input'}
|
||||
<VerticallyCentered>
|
||||
<form noValidate onSubmit={handleSubmit}>
|
||||
<Typography
|
||||
mb={2}
|
||||
variant="body2"
|
||||
color="text.secondary">
|
||||
{constants.ENTER_TWO_FACTOR_OTP}
|
||||
</Typography>
|
||||
<Box my={2}>
|
||||
<OtpInput
|
||||
ref={otpInputRef}
|
||||
shouldAutoFocus
|
||||
value={values.otp}
|
||||
onChange={onChange(
|
||||
handleChange('otp'),
|
||||
submitForm
|
||||
)}
|
||||
numInputs={6}
|
||||
separator={'-'}
|
||||
isInputNum
|
||||
className={'otp-input'}
|
||||
/>
|
||||
{errors.otp && (
|
||||
<CenteredFlex sx={{ mt: 1 }}>
|
||||
<InvalidInputMessage>
|
||||
{constants.INCORRECT_CODE}
|
||||
</InvalidInputMessage>
|
||||
</CenteredFlex>
|
||||
)}
|
||||
</Box>
|
||||
<SubmitButton
|
||||
buttonText={props.buttonText}
|
||||
loading={waiting}
|
||||
disabled={values.otp.length < 6}
|
||||
/>
|
||||
{errors.otp && (
|
||||
<CenteredFlex sx={{ mt: 1 }}>
|
||||
<InvalidInputMessage>
|
||||
{constants.INCORRECT_CODE}
|
||||
</InvalidInputMessage>
|
||||
</CenteredFlex>
|
||||
)}
|
||||
</Box>
|
||||
<SubmitButton
|
||||
buttonText={props.buttonText}
|
||||
loading={waiting}
|
||||
disabled={values.otp.length < 6}
|
||||
/>
|
||||
</form>
|
||||
</form>
|
||||
</VerticallyCentered>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
|
|
|
@ -3,8 +3,9 @@ import constants from 'utils/strings/constants';
|
|||
import { default as FileUploadIcon } from '@mui/icons-material/ImageOutlined';
|
||||
import { default as FolderUploadIcon } from '@mui/icons-material/PermMediaOutlined';
|
||||
import GoogleIcon from '@mui/icons-material/Google';
|
||||
import DialogBox from 'components/DialogBox';
|
||||
import { UploadTypeOption } from './option';
|
||||
import DialogTitleWithCloseButton from 'components/DialogBox/TitleWithCloseButton';
|
||||
import { Dialog, DialogContent } from '@mui/material';
|
||||
|
||||
export default function UploadTypeSelector({
|
||||
onHide,
|
||||
|
@ -14,29 +15,27 @@ export default function UploadTypeSelector({
|
|||
uploadGoogleTakeoutZips,
|
||||
}) {
|
||||
return (
|
||||
<DialogBox
|
||||
attributes={{
|
||||
title: constants.UPLOAD,
|
||||
}}
|
||||
open={show}
|
||||
size={'xs'}
|
||||
onClose={onHide}
|
||||
titleCloseButton>
|
||||
<UploadTypeOption
|
||||
uploadFunc={uploadFiles}
|
||||
Icon={FileUploadIcon}
|
||||
uploadName={constants.UPLOAD_FILES}
|
||||
/>
|
||||
<UploadTypeOption
|
||||
uploadFunc={uploadFolders}
|
||||
Icon={FolderUploadIcon}
|
||||
uploadName={constants.UPLOAD_DIRS}
|
||||
/>
|
||||
<UploadTypeOption
|
||||
uploadFunc={uploadGoogleTakeoutZips}
|
||||
Icon={GoogleIcon}
|
||||
uploadName={constants.UPLOAD_GOOGLE_TAKEOUT}
|
||||
/>
|
||||
</DialogBox>
|
||||
<Dialog open={show} maxWidth={'xs'} onClose={onHide}>
|
||||
<DialogTitleWithCloseButton onClose={onHide}>
|
||||
{constants.UPLOAD}
|
||||
</DialogTitleWithCloseButton>
|
||||
<DialogContent sx={{ '&&&&': { pt: 0 } }}>
|
||||
<UploadTypeOption
|
||||
uploadFunc={uploadFiles}
|
||||
Icon={FileUploadIcon}
|
||||
uploadName={constants.UPLOAD_FILES}
|
||||
/>
|
||||
<UploadTypeOption
|
||||
uploadFunc={uploadFolders}
|
||||
Icon={FolderUploadIcon}
|
||||
uploadName={constants.UPLOAD_DIRS}
|
||||
/>
|
||||
<UploadTypeOption
|
||||
uploadFunc={uploadGoogleTakeoutZips}
|
||||
Icon={GoogleIcon}
|
||||
uploadName={constants.UPLOAD_GOOGLE_TAKEOUT}
|
||||
/>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ export default function Home() {
|
|||
};
|
||||
return (
|
||||
<FormContainer>
|
||||
<FormPaper sx={{ maxWidth: '400px' }}>
|
||||
<FormPaper sx={{ maxWidth: '410px' }}>
|
||||
<FormTitle>{constants.TWO_FACTOR}</FormTitle>
|
||||
<VerifyTwoFactor
|
||||
onSubmit={onSubmit}
|
||||
|
|
Loading…
Reference in a new issue