Merge branch 'ui-redesign' into sidebar-items-redesign

This commit is contained in:
Abhinav 2022-05-13 14:06:27 +05:30
commit e70011b55f
46 changed files with 691 additions and 570 deletions

View file

@ -80,7 +80,7 @@
"@types/react-select": "^4.0.15", "@types/react-select": "^4.0.15",
"@types/react-window": "^1.8.2", "@types/react-window": "^1.8.2",
"@types/react-window-infinite-loader": "^1.0.3", "@types/react-window-infinite-loader": "^1.0.3",
"@types/styled-components": "^5.1.3", "@types/styled-components": "^5.1.25",
"@types/yup": "^0.29.7", "@types/yup": "^0.29.7",
"babel-plugin-styled-components": "^1.11.1", "babel-plugin-styled-components": "^1.11.1",
"eslint": "^7.27.0", "eslint": "^7.27.0",

View file

@ -3,7 +3,7 @@ import { FreeFlowText, IconButton } from './Container';
import CopyIcon from './icons/CopyIcon'; import CopyIcon from './icons/CopyIcon';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Tooltip, OverlayTrigger } from 'react-bootstrap'; import { Tooltip, OverlayTrigger } from 'react-bootstrap';
import TickIcon from './icons/TickIcon'; import TickIcon from '@mui/icons-material/Done';
import EnteSpinner from './EnteSpinner'; import EnteSpinner from './EnteSpinner';
const Wrapper = styled.div` const Wrapper = styled.div`

View file

@ -1,111 +0,0 @@
import { CollectionSummaries } from 'types/collection';
interface Iprops {
isOpen: boolean;
close: () => void;
collectionSummaries: CollectionSummaries;
setActiveCollection: (id?: number) => void;
}
import * as React from 'react';
import DialogContent from '@mui/material/DialogContent';
import Typography from '@mui/material/Typography';
import constants from 'utils/strings/constants';
import { FlexWrapper, SpaceBetweenFlex } from 'components/Container';
import { LargerCollectionTile } from './styledComponents';
import CollectionCard from './CollectionCard';
import Divider from '@mui/material/Divider';
import CollectionSort from 'components/pages/gallery/CollectionSort';
import { CollectionType, COLLECTION_SORT_BY } from 'constants/collection';
import { DialogTitleWithCloseButton } from 'components/MessageDialog';
import { sortCollectionSummaries } from 'services/collectionService';
import {
Transition,
FloatingDrawer,
} from 'components/Collections/FloatingDrawer';
import { useLocalState } from 'hooks/useLocalState';
import { LS_KEYS } from 'utils/storage/localStorage';
const LeftSlideTransition = Transition('up');
export default function AllCollections(props: Iprops) {
const { collectionSummaries, isOpen, close, setActiveCollection } = props;
const onCollectionClick = (collectionID: number) => {
setActiveCollection(collectionID);
close();
};
const [collectionSortBy, setCollectionSortBy] =
useLocalState<COLLECTION_SORT_BY>(
LS_KEYS.COLLECTION_SORT_BY,
COLLECTION_SORT_BY.UPDATION_TIME_DESCENDING
);
return (
<>
<FloatingDrawer
position="right"
TransitionComponent={LeftSlideTransition}
onClose={close}
open={isOpen}>
<DialogTitleWithCloseButton onClose={close}>
<Typography variant="h6">
<strong>{constants.ALL_ALBUMS}</strong>
</Typography>
<SpaceBetweenFlex>
<Typography variant="subtitle1">
{`${[...props.collectionSummaries.keys()].length} ${
constants.ALBUMS
}`}
</Typography>
<CollectionSort
activeSortBy={collectionSortBy}
setCollectionSortBy={setCollectionSortBy}
/>
</SpaceBetweenFlex>
</DialogTitleWithCloseButton>
<Divider />
<DialogContent>
<FlexWrapper>
{sortCollectionSummaries(
[...collectionSummaries.values()].filter(
(x) =>
x.collectionAttributes.type !==
CollectionType.system
),
collectionSortBy
).map(
({
latestFile,
collectionAttributes,
fileCount,
}) => (
<CollectionCard
key={collectionAttributes.id}
latestFile={latestFile}
onClick={() =>
onCollectionClick(
collectionAttributes.id
)
}
customCollectionTile={LargerCollectionTile}>
<div>
<Typography>
<strong>
{collectionAttributes.name}
</strong>
</Typography>
<Typography>
{fileCount} {constants.PHOTOS}
</Typography>
</div>
</CollectionCard>
)
)}
</FlexWrapper>
</DialogContent>
</FloatingDrawer>
</>
);
}

View file

@ -0,0 +1,37 @@
import { Typography } from '@mui/material';
import constants from 'utils/strings/constants';
import React from 'react';
import CollectionCard from '../CollectionCard';
export default function AllCollectionCard({
onCollectionClick,
collectionAttributes,
latestFile,
fileCount,
}) {
return (
<CollectionCard
large
latestFile={latestFile}
onClick={() => onCollectionClick(collectionAttributes.id)}>
<div>
<Typography
css={`
font-size: 14px;
font-weight: 600;
line-height: 20px;
`}>
{collectionAttributes.name}
</Typography>
<Typography
css={`
font-size: 14px;
font-weight: 400;
line-height: 20px;
`}>
{fileCount} {constants.PHOTOS}
</Typography>
</div>
</CollectionCard>
);
}

View file

@ -0,0 +1,44 @@
import React, { useState } from 'react';
import { COLLECTION_SORT_BY } from 'constants/collection';
import Menu from '@mui/material/Menu';
import { IconButton, styled } from '@mui/material';
import SortIcon from '@mui/icons-material/Sort';
import CollectionSortOptions from './options';
export interface CollectionSortProps {
setCollectionSortBy: (sortBy: COLLECTION_SORT_BY) => void;
activeSortBy: COLLECTION_SORT_BY;
}
const StyledMenu = styled(Menu)`
& .MuiPaper-root {
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.16);
}
`;
export default function CollectionSort(props: CollectionSortProps) {
const [sortByEl, setSortByEl] = useState(null);
const handleClose = () => setSortByEl(null);
return (
<>
<IconButton
onClick={(event) => setSortByEl(event.currentTarget)}
aria-controls={sortByEl ? 'collection-sort' : undefined}
aria-haspopup="true"
aria-expanded={sortByEl ? 'true' : undefined}>
<SortIcon />
</IconButton>
<StyledMenu
id="collection-sort"
anchorEl={sortByEl}
open={Boolean(sortByEl)}
onClose={handleClose}
MenuListProps={{
disablePadding: true,
'aria-labelledby': 'collection-sort',
}}>
<CollectionSortOptions {...props} close={handleClose} />
</StyledMenu>
</>
);
}

View file

@ -0,0 +1,35 @@
import React from 'react';
import { MenuItem, ListItemIcon, ListItemText } from '@mui/material';
import { COLLECTION_SORT_BY } from 'constants/collection';
import TickIcon from '@mui/icons-material/Done';
import { CollectionSortProps } from '.';
export interface SortOptionProps extends CollectionSortProps {
close: () => void;
}
const SortByOptionCreator =
({ setCollectionSortBy, activeSortBy, close }: SortOptionProps) =>
(props: { sortBy: COLLECTION_SORT_BY; children: any }) => {
const handleClick = () => {
setCollectionSortBy(props.sortBy);
close();
};
return (
<MenuItem onClick={handleClick} style={{ paddingLeft: '5px' }}>
<ListItemIcon style={{ minWidth: '25px' }}>
{activeSortBy === props.sortBy && (
<TickIcon
css={`
height: 16px;
width: 16px;
`}
/>
)}
</ListItemIcon>
<ListItemText>{props.children}</ListItemText>
</MenuItem>
);
};
export default SortByOptionCreator;

View file

@ -0,0 +1,26 @@
import React from 'react';
import { MenuList } from '@mui/material';
import { COLLECTION_SORT_BY } from 'constants/collection';
import constants from 'utils/strings/constants';
import SortByOptionCreator, { SortOptionProps } from './optionCreator';
export default function CollectionSortOptions(props: SortOptionProps) {
const SortByOption = SortByOptionCreator(props);
return (
<MenuList>
<SortByOption sortBy={COLLECTION_SORT_BY.NAME}>
{constants.SORT_BY_NAME}
</SortByOption>
<SortByOption sortBy={COLLECTION_SORT_BY.CREATION_TIME_DESCENDING}>
{constants.SORT_BY_CREATION_TIME_DESCENDING}
</SortByOption>
<SortByOption sortBy={COLLECTION_SORT_BY.CREATION_TIME_ASCENDING}>
{constants.SORT_BY_CREATION_TIME_ASCENDING}
</SortByOption>
<SortByOption sortBy={COLLECTION_SORT_BY.UPDATION_TIME_DESCENDING}>
{constants.SORT_BY_UPDATION_TIME_DESCENDING}
</SortByOption>
</MenuList>
);
}

View file

@ -0,0 +1,30 @@
import React from 'react';
import { DialogContent } from '@mui/material';
import { FlexWrapper } from 'components/Container';
import AllCollectionCard from './CollectionCard';
export default function AllCollectionContent({
sortedCollectionSummaries,
onCollectionClick,
}) {
return (
<DialogContent>
<FlexWrapper
style={{
flexWrap: 'wrap',
}}>
{sortedCollectionSummaries.map(
({ latestFile, collectionAttributes, fileCount }) => (
<AllCollectionCard
onCollectionClick={onCollectionClick}
collectionAttributes={collectionAttributes}
key={collectionAttributes.id}
latestFile={latestFile}
fileCount={fileCount}
/>
)
)}
</FlexWrapper>
</DialogContent>
);
}

View file

@ -0,0 +1,46 @@
import React from 'react';
import { DialogTitle, IconButton, Typography } from '@mui/material';
import { SpaceBetweenFlex } from 'components/Container';
import CollectionSort from 'components/Collections/AllCollections/CollectionSort';
import constants from 'utils/strings/constants';
import Close from '@mui/icons-material/Close';
export default function AllCollectionsHeader({
onClose,
collectionCount,
collectionSortBy,
setCollectionSortBy,
}) {
return (
<DialogTitle>
<SpaceBetweenFlex>
<Typography
css={`
font-size: 24px;
font-weight: 600;
line-height: 36px;
`}>
{constants.ALL_ALBUMS}
</Typography>
<IconButton onClick={onClose}>
<Close />
</IconButton>
</SpaceBetweenFlex>
<SpaceBetweenFlex>
<Typography
css={`
font-size: 24px;
font-weight: 600;
line-height: 36px;
`}
color={'text.secondary'}>
{`${collectionCount} ${constants.ALBUMS}`}
</Typography>
<CollectionSort
activeSortBy={collectionSortBy}
setCollectionSortBy={setCollectionSortBy}
/>
</SpaceBetweenFlex>
</DialogTitle>
);
}

View file

@ -0,0 +1,67 @@
import React, { useMemo } from 'react';
import Divider from '@mui/material/Divider';
import { CollectionType, COLLECTION_SORT_BY } from 'constants/collection';
import { sortCollectionSummaries } from 'services/collectionService';
import {
Transition,
FloatingDrawer,
} from 'components/Collections/FloatingDrawer';
import { useLocalState } from 'hooks/useLocalState';
import { LS_KEYS } from 'utils/storage/localStorage';
import AllCollectionsHeader from './header';
import { CollectionSummaries } from 'types/collection';
import AllCollectionContent from './content';
interface Iprops {
isOpen: boolean;
close: () => void;
collectionSummaries: CollectionSummaries;
setActiveCollection: (id?: number) => void;
}
const LeftSlideTransition = Transition('up');
export default function AllCollections(props: Iprops) {
const { collectionSummaries, isOpen, close, setActiveCollection } = props;
const [collectionSortBy, setCollectionSortBy] =
useLocalState<COLLECTION_SORT_BY>(
LS_KEYS.COLLECTION_SORT_BY,
COLLECTION_SORT_BY.UPDATION_TIME_DESCENDING
);
const sortedCollectionSummaries = useMemo(
() =>
sortCollectionSummaries(
[...collectionSummaries.values()].filter(
(x) => x.collectionAttributes.type !== CollectionType.system
),
collectionSortBy
),
[collectionSortBy, collectionSummaries]
);
const onCollectionClick = (collectionID: number) => {
setActiveCollection(collectionID);
close();
};
return (
<FloatingDrawer
TransitionComponent={LeftSlideTransition}
onClose={close}
open={isOpen}>
<AllCollectionsHeader
onClose={close}
collectionCount={props.collectionSummaries.size}
collectionSortBy={collectionSortBy}
setCollectionSortBy={setCollectionSortBy}
/>
<Divider />
<AllCollectionContent
sortedCollectionSummaries={sortedCollectionSummaries}
onCollectionClick={onCollectionClick}
/>
</FloatingDrawer>
);
}

View file

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { EnteFile } from 'types/file'; import { EnteFile } from 'types/file';
import { CollectionTileWrapper, ActiveIndicator } from './styledComponents'; import { CollectionTileWrapper, ActiveIndicator } from '../styledComponents';
import CollectionCard from './CollectionCard'; import CollectionCard from '../CollectionCard';
const CollectionCardWithActiveIndicator = React.forwardRef( const CollectionCardWithActiveIndicator = React.forwardRef(
( (

View file

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import constants from 'utils/strings/englishConstants'; import constants from 'utils/strings/englishConstants';
import { CollectionTitleWithDashedBorder } from './styledComponents'; import { CollectionTitleWithDashedBorder } from '../styledComponents';
export const CreateNewCollectionTile = (props) => { export const CreateNewCollectionTile = (props) => {
return ( return (

View file

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import styled, { css } from 'styled-components'; import styled, { css } from 'styled-components';
import NavigateNext from '../icons/NavigateNext'; import NavigateNextIcon from '@mui/icons-material/NavigateNext';
export enum SCROLL_DIRECTION { export enum SCROLL_DIRECTION {
LEFT = -1, LEFT = -1,
@ -8,15 +8,18 @@ export enum SCROLL_DIRECTION {
} }
const Wrapper = styled.button<{ direction: SCROLL_DIRECTION }>` const Wrapper = styled.button<{ direction: SCROLL_DIRECTION }>`
position: absolute;
top: 7px; top: 7px;
height: 50px; height: 50px;
width: 50px; width: 50px;
border: none;
padding: 0;
margin: 0;
border-radius: 50%; border-radius: 50%;
background-color: ${({ theme }) => theme.palette.background.paper}; background-color: ${({ theme }) => theme.palette.background.paper};
border: none;
color: ${({ theme }) => theme.palette.text.primary}; color: ${({ theme }) => theme.palette.text.primary};
position: absolute;
${(props) => ${(props) =>
props.direction === SCROLL_DIRECTION.LEFT props.direction === SCROLL_DIRECTION.LEFT
? css` ? css`
@ -38,15 +41,11 @@ const Wrapper = styled.button<{ direction: SCROLL_DIRECTION }>`
height: 30px; height: 30px;
width: 30px; width: 30px;
} }
&:hover {
color: #fff;
}
`; `;
const NavigationButton = ({ scrollDirection, ...rest }) => ( const NavigationButton = ({ scrollDirection, ...rest }) => (
<Wrapper direction={scrollDirection} {...rest}> <Wrapper direction={scrollDirection} {...rest}>
<NavigateNext /> <NavigateNextIcon />
</Wrapper> </Wrapper>
); );
export default NavigationButton; export default NavigationButton;

View file

@ -1,6 +1,6 @@
import NavigationButton, { import NavigationButton, {
SCROLL_DIRECTION, SCROLL_DIRECTION,
} from 'components/Collections/NavigationButton'; } from 'components/Collections/CollectionBar/NavigationButton';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { Collection, CollectionSummaries } from 'types/collection'; import { Collection, CollectionSummaries } from 'types/collection';
import constants from 'utils/strings/constants'; import constants from 'utils/strings/constants';
@ -12,7 +12,7 @@ import {
ScrollContainer, ScrollContainer,
PaddedSpaceBetweenFlex, PaddedSpaceBetweenFlex,
} from 'components/Collections/styledComponents'; } from 'components/Collections/styledComponents';
import CollectionCardWithActiveIndicator from 'components/Collections/CollectionCardWithActiveIndicator'; import CollectionCardWithActiveIndicator from 'components/Collections/CollectionBar/CollectionCardWithActiveIndicator';
import useComponentScroll from 'hooks/useComponentScroll'; import useComponentScroll from 'hooks/useComponentScroll';
import useWindowSize from 'hooks/useWindowSize'; import useWindowSize from 'hooks/useWindowSize';

View file

@ -3,15 +3,15 @@ import { GalleryContext } from 'pages/gallery';
import { useState, useContext, useEffect } from 'react'; import { useState, useContext, useEffect } from 'react';
import downloadManager from 'services/downloadManager'; import downloadManager from 'services/downloadManager';
import { EnteFile } from 'types/file'; import { EnteFile } from 'types/file';
import { CollectionTile } from './styledComponents'; import { CollectionTile, LargerCollectionTile } from './styledComponents';
export default function CollectionCard(props: { export default function CollectionCard(props: {
children?: any; children?: any;
latestFile: EnteFile; latestFile: EnteFile;
onClick: () => void; onClick: () => void;
customCollectionTile?: any; large?: boolean;
}) { }) {
const { latestFile: file, onClick, children, customCollectionTile } = props; const { latestFile: file, onClick, children, large } = props;
const [coverImageURL, setCoverImageURL] = useState(null); const [coverImageURL, setCoverImageURL] = useState(null);
const galleryContext = useContext(GalleryContext); const galleryContext = useContext(GalleryContext);
@ -28,7 +28,7 @@ export default function CollectionCard(props: {
}; };
main(); main();
}, [file]); }, [file]);
const UsedCollectionTile = customCollectionTile ?? CollectionTile; const UsedCollectionTile = large ? LargerCollectionTile : CollectionTile;
return ( return (
<UsedCollectionTile coverImgURL={coverImageURL} onClick={onClick}> <UsedCollectionTile coverImgURL={coverImageURL} onClick={onClick}>
{children} {children}

View file

@ -25,10 +25,19 @@ export default function collectionInfo(props: Iprops) {
return ( return (
<PaddedSpaceBetweenFlex> <PaddedSpaceBetweenFlex>
<div> <div>
<Typography variant="h5"> <Typography
<strong>{collectionAttributes.name}</strong> css={`
font-size: 24px;
font-weight: 600;
line-height: 36px;
`}>
{collectionAttributes.name}
</Typography> </Typography>
<Typography variant="subtitle1"> <Typography
css={`
font-size: 14px;
line-height: 20px;
`}>
{fileCount} {constants.PHOTOS} {fileCount} {constants.PHOTOS}
</Typography> </Typography>
</div> </div>

View file

@ -1,10 +1,17 @@
import React from 'react'; import React from 'react';
import { Dialog, DialogContent, TextField } from '@mui/material'; import {
Dialog,
DialogContent,
DialogTitle,
IconButton,
TextField,
} from '@mui/material';
import constants from 'utils/strings/constants'; import constants from 'utils/strings/constants';
import SubmitButton from 'components/SubmitButton'; import SubmitButton from 'components/SubmitButton';
import { Formik } from 'formik'; import { Formik } from 'formik';
import * as Yup from 'yup'; import * as Yup from 'yup';
import { DialogTitleWithCloseButton } from 'components/MessageDialog'; import { SpaceBetweenFlex } from 'components/Container';
import Close from '@mui/icons-material/Close';
export interface CollectionNamerAttributes { export interface CollectionNamerAttributes {
callback: (name) => void; callback: (name) => void;
@ -37,9 +44,14 @@ export default function CollectionNamer({ attributes, ...props }: Props) {
return ( return (
<Dialog open={props.show} onClose={props.onHide} maxWidth="xs"> <Dialog open={props.show} onClose={props.onHide} maxWidth="xs">
<DialogTitleWithCloseButton onClose={props.onHide}> <DialogTitle>
{attributes?.title} <SpaceBetweenFlex>
</DialogTitleWithCloseButton> {attributes?.title}
<IconButton onClick={props.onHide}>
<Close />
</IconButton>
</SpaceBetweenFlex>
</DialogTitle>
<DialogContent> <DialogContent>
<Formik<formValues> <Formik<formValues>
initialValues={{ initialValues={{

View file

@ -172,6 +172,7 @@ const CollectionOptions = (props: CollectionOptionsProps) => {
open={Boolean(optionEl)} open={Boolean(optionEl)}
onClose={handleClose} onClose={handleClose}
MenuListProps={{ MenuListProps={{
disablePadding: true,
'aria-labelledby': 'collection-options', 'aria-labelledby': 'collection-options',
}}> }}>
<Paper sx={{ borderRadius: '10px' }}> <Paper sx={{ borderRadius: '10px' }}>

View file

@ -2,22 +2,20 @@ import { Dialog, Slide, styled } from '@mui/material';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
export const FloatingDrawer = styled(Dialog)<{ position: 'left' | 'right' }>( export const FloatingDrawer = styled(Dialog)(({ theme }) => ({
({ position, theme }) => ({ '& .MuiDialog-container': {
'& .MuiDialogContent-root': { justifyContent: 'flex-end',
padding: theme.spacing(2), },
}, '& .MuiPaper-root': {
'& .MuiDialogActions-root': { maxWidth: '498px',
padding: theme.spacing(1), },
}, '& .MuiDialogTitle-root': {
'& .MuiPaper-root': { padding: theme.spacing(3, 2),
maxWidth: '510px', },
}, '& .MuiDialogContent-root': {
'& .MuiDialog-container': { padding: theme.spacing(2),
justifyContent: position === 'left' ? 'flex-start' : 'flex-end', },
}, }));
})
);
FloatingDrawer.propTypes = { FloatingDrawer.propTypes = {
children: PropTypes.node, children: PropTypes.node,

View file

@ -13,7 +13,7 @@ export const CollectionBarWrapper = styled.div`
@media (max-width: ${IMAGE_CONTAINER_MAX_WIDTH * 4}px) { @media (max-width: ${IMAGE_CONTAINER_MAX_WIDTH * 4}px) {
padding: 0 4px; padding: 0 4px;
} }
border-bottom: 1px solid ${({ theme }) => theme.palette.grey.A400}; border-bottom: 1px solid ${({ theme }) => theme.palette.grey.A200};
`; `;
export const PaddedSpaceBetweenFlex = styled(SpaceBetweenFlex)` export const PaddedSpaceBetweenFlex = styled(SpaceBetweenFlex)`
@ -37,7 +37,6 @@ export const ScrollContainer = styled.div`
export const CollectionTile = styled.div<{ export const CollectionTile = styled.div<{
coverImgURL?: string; coverImgURL?: string;
}>` }>`
flex-shrink: 0;
display: flex; display: flex;
width: 80px; width: 80px;
height: 64px; height: 64px;
@ -50,10 +49,12 @@ export const CollectionTile = styled.div<{
background-image: url(${({ coverImgURL }) => coverImgURL}); background-image: url(${({ coverImgURL }) => coverImgURL});
background-size: cover; background-size: cover;
border: 1px solid ${({ theme }) => theme.palette.grey.A200}; border: 1px solid ${({ theme }) => theme.palette.grey.A200};
font-size: 14px;
line-height: 20px;
`; `;
export const CollectionTileWrapper = styled.div` export const CollectionTileWrapper = styled.div`
margin-right: 6px; margin-right: 4px;
`; `;
export const ActiveIndicator = styled.div` export const ActiveIndicator = styled.div`
@ -72,7 +73,7 @@ export const LargerCollectionTile = styled(CollectionTile)`
width: 150px; width: 150px;
height: 150px; height: 150px;
align-items: flex-start; align-items: flex-start;
margin: 4px; margin: 2px;
`; `;
export const CollectionTitleWithDashedBorder = styled(CollectionTile)` export const CollectionTitleWithDashedBorder = styled(CollectionTile)`

View file

@ -1,3 +1,4 @@
import { Box } from '@mui/material';
import styled from 'styled-components'; import styled from 'styled-components';
const Container = styled.div` const Container = styled.div`
@ -54,9 +55,8 @@ export const Value = styled.div<{ width?: string }>`
color: #ddd; color: #ddd;
`; `;
export const FlexWrapper = styled.div` export const FlexWrapper = styled(Box)`
display: flex; display: flex;
flex-wrap: wrap;
align-items: center; align-items: center;
`; `;
@ -70,6 +70,14 @@ export const SpaceBetweenFlex = styled(FlexWrapper)`
justify-content: space-between; justify-content: space-between;
`; `;
export const CenteredFlex = styled(FlexWrapper)`
justify-content: center;
`;
export const FluidContainer = styled(FlexWrapper)`
flex: 1;
`;
export const InvertedIconButton = styled(IconButton)` export const InvertedIconButton = styled(IconButton)`
background-color: ${({ theme }) => theme.palette.primary.main}; background-color: ${({ theme }) => theme.palette.primary.main};
color: ${({ theme }) => theme.palette.background.default}; color: ${({ theme }) => theme.palette.background.default};

View file

@ -0,0 +1,26 @@
import React from 'react';
import { DialogTitle, IconButton } from '@mui/material';
import CloseIcon from '@mui/icons-material/Close';
import { SpaceBetweenFlex } from 'components/Container';
const DialogTitleWithCloseButton = (props) => {
const { children, onClose, ...other } = props;
return (
<DialogTitle {...other}>
<SpaceBetweenFlex>
{children}
{onClose && (
<IconButton
aria-label="close"
onClick={onClose}
sx={{ float: 'right' }}>
<CloseIcon />
</IconButton>
)}
</SpaceBetweenFlex>
</DialogTitle>
);
};
export default DialogTitleWithCloseButton;

View file

@ -1,8 +1,5 @@
import DialogTitle from '@mui/material/DialogTitle';
import IconButton from '@mui/material/IconButton';
import React from 'react'; import React from 'react';
import constants from 'utils/strings/constants'; import constants from 'utils/strings/constants';
import CloseIcon from '@mui/icons-material/Close';
import { import {
Breakpoint, Breakpoint,
Button, Button,
@ -12,6 +9,7 @@ import {
DialogContentText, DialogContentText,
Divider, Divider,
} from '@mui/material'; } from '@mui/material';
import DialogTitleWithCloseButton from './TitleWithCloseButton';
export type ButtonColors = export type ButtonColors =
| 'inherit' | 'inherit'
@ -46,29 +44,6 @@ type Props = React.PropsWithChildren<{
size?: Breakpoint; size?: Breakpoint;
}>; }>;
export const DialogTitleWithCloseButton = (props) => {
const { children, onClose, ...other } = props;
return (
<DialogTitle sx={{ m: 0, p: 2 }} {...other}>
{children}
{onClose ? (
<IconButton
aria-label="close"
onClick={onClose}
sx={{
position: 'absolute',
right: 8,
top: 8,
color: (theme) => theme.palette.grey[400],
}}>
<CloseIcon />
</IconButton>
) : null}
</DialogTitle>
);
};
export default function MessageDialog({ export default function MessageDialog({
attributes, attributes,
children, children,

View file

@ -38,7 +38,7 @@ import { livePhotoBtnHTML } from 'components/LivePhotoBtn';
import { logError } from 'utils/sentry'; import { logError } from 'utils/sentry';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import TickIcon from 'components/icons/TickIcon'; import TickIcon from '@mui/icons-material/Done';
import { Formik } from 'formik'; import { Formik } from 'formik';
import * as Yup from 'yup'; import * as Yup from 'yup';
import EnteSpinner from 'components/EnteSpinner'; import EnteSpinner from 'components/EnteSpinner';

View file

@ -1,44 +1,38 @@
import React from 'react'; import React, { FC } from 'react';
import { Button } from '@mui/material'; import { Button, ButtonProps } from '@mui/material';
import NavigateNextIcon from '@mui/icons-material/NavigateNext'; import NavigateNextIcon from '@mui/icons-material/NavigateNext';
import { FluidContainer } from 'components/Container';
interface IProps { interface IProps {
children: any;
bgDark?: boolean;
hideArrow?: boolean; hideArrow?: boolean;
onClick: () => void; smallerArrow?: boolean;
color?:
| 'inherit'
| 'danger'
| 'primary'
| 'secondary'
| 'success'
| 'error'
| 'info'
| 'warning';
} }
export default function SidebarButton({ const SidebarButton: FC<ButtonProps<'button', IProps>> = ({
children, children,
bgDark,
hideArrow, hideArrow,
smallerArrow,
sx,
...props ...props
}: IProps) { }) => {
return ( return (
<Button <Button
{...props}
variant="text" variant="text"
sx={{ fullWidth
width: '100%', sx={{ my: 0.5, px: 1, py: '10px', ...sx }}
marginBottom: '16px', css={`
display: 'flex', font-size: 16px;
justifyContent: 'space-between', font-weight: 600;
bgcolor: bgDark && 'grey.800', line-height: 24px;
padding: '10px', letter-spacing: 0em;
borderRadius: '8px', `}
textTransform: 'none', {...props}>
fontSize: '18px', <FluidContainer>{children}</FluidContainer>
}}> {!hideArrow && (
{children} <NavigateNextIcon
{!hideArrow && <NavigateNextIcon />} fontSize={smallerArrow ? 'small' : 'medium'}
/>
)}
</Button> </Button>
); );
} };
export default SidebarButton;

View file

@ -2,6 +2,7 @@ import { Typography, IconButton } from '@mui/material';
import React from 'react'; import React from 'react';
import constants from 'utils/strings/constants'; import constants from 'utils/strings/constants';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import { SpaceBetweenFlex } from 'components/Container';
interface IProps { interface IProps {
closeSidebar: () => void; closeSidebar: () => void;
@ -9,21 +10,18 @@ interface IProps {
export default function HeaderSection({ closeSidebar }: IProps) { export default function HeaderSection({ closeSidebar }: IProps) {
return ( return (
<> <SpaceBetweenFlex>
<Typography variant="h6"> <Typography
<strong>{constants.ENTE}</strong> css={`
font-size: 18px;
font-weight: 600;
line-height: 24px;
`}>
{constants.ENTE}
</Typography> </Typography>
<IconButton <IconButton aria-label="close" onClick={closeSidebar}>
aria-label="close" <CloseIcon fontSize="small" />
onClick={closeSidebar}
sx={{
position: 'absolute',
right: 16,
top: 16,
color: (theme) => theme.palette.grey[400],
}}>
<CloseIcon />
</IconButton> </IconButton>
</> </SpaceBetweenFlex>
); );
} }

View file

@ -10,12 +10,16 @@ import { getToken } from 'utils/common/key';
import isElectron from 'is-electron'; import isElectron from 'is-electron';
import { downloadApp, initiateEmail } from 'utils/common'; import { downloadApp, initiateEmail } from 'utils/common';
import { GalleryContext } from 'pages/gallery'; import { GalleryContext } from 'pages/gallery';
import { useLocalState } from 'hooks/useLocalState';
import { LS_KEYS } from 'utils/storage/localStorage';
import { UserDetails } from 'types/user';
export default function HelpSection({ userDetails }) { export default function HelpSection() {
const { setDialogMessage } = useContext(GalleryContext); const [userDetails] = useLocalState<UserDetails>(LS_KEYS.USER_DETAILS);
const [exportModalView, setExportModalView] = useState(false); const [exportModalView, setExportModalView] = useState(false);
const { setDialogMessage } = useContext(GalleryContext);
function openFeedbackURL() { function openFeedbackURL() {
const feedbackURL: string = `${getEndpoint()}/users/feedback?token=${encodeURIComponent( const feedbackURL: string = `${getEndpoint()}/users/feedback?token=${encodeURIComponent(
getToken() getToken()

View file

@ -1,25 +0,0 @@
import React, { useState } from 'react';
import { Typography } from '@mui/material';
import { SpaceBetweenFlex } from 'components/Container';
import ThemeToggler from './ThemeToggler';
import { UserDetails } from 'types/user';
interface IProps {
userDetails: UserDetails;
}
export enum THEMES {
LIGHT,
DARK,
}
export default function InfoSection({ userDetails }: IProps) {
const [theme, setTheme] = useState<THEMES>(THEMES.DARK);
return (
<SpaceBetweenFlex style={{ marginBottom: '20px' }}>
<Typography pl="5px">{userDetails?.email}</Typography>
<ThemeToggler theme={theme} setTheme={setTheme} />
</SpaceBetweenFlex>
);
}

View file

@ -0,0 +1,40 @@
import React, { FC } from 'react';
import { Box, ButtonProps } from '@mui/material';
import SidebarButton from './Button';
import { DotSeparator } from './styledComponents';
interface IProps {
hideArrow?: boolean;
icon: JSX.Element;
label: JSX.Element | string;
count: number;
}
const NavigationButton: FC<ButtonProps<'button', IProps>> = ({
icon,
label,
count,
...props
}) => {
return (
<SidebarButton
smallerArrow
variant="contained"
color="secondary"
sx={{ px: '12px' }}
css={`
font-size: 14px;
line-height: 20px;
font-weight: 500;
`}
{...props}>
<Box mr={'12px'}>{icon}</Box>
{label}
<DotSeparator />
<Box component={'span'} sx={{ color: 'text.secondary' }}>
{count}
</Box>
</SidebarButton>
);
};
export default NavigationButton;

View file

@ -1,66 +1,46 @@
import React, { useContext } from 'react'; import React, { useContext } from 'react';
import SidebarButton from './Button';
import constants from 'utils/strings/constants'; import constants from 'utils/strings/constants';
import { GalleryContext } from 'pages/gallery'; import { GalleryContext } from 'pages/gallery';
import { ARCHIVE_SECTION, TRASH_SECTION } from 'constants/collection'; import { ARCHIVE_SECTION, TRASH_SECTION } from 'constants/collection';
import DeleteIcon from '@mui/icons-material/Delete'; import DeleteIcon from '@mui/icons-material/Delete';
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'; import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
import { Box, Typography } from '@mui/material';
import { FlexWrapper } from 'components/Container';
import { CollectionSummaries } from 'types/collection'; import { CollectionSummaries } from 'types/collection';
import NavigationButton from './NavigationButton';
interface Iprops { interface Iprops {
closeSidebar: () => void; closeSidebar: () => void;
collectionSummaries: CollectionSummaries; collectionSummaries: CollectionSummaries;
} }
const DotSeparator = () => (
<Typography color="text.secondary" ml="10px" mr="10px" fontWeight={700}>
{'·'}
</Typography>
);
export default function NavigationSection({ export default function NavigationSection({
closeSidebar, closeSidebar,
collectionSummaries, collectionSummaries,
}: Iprops) { }: Iprops) {
const galleryContext = useContext(GalleryContext); const galleryContext = useContext(GalleryContext);
const openArchiveSection = () => {
galleryContext.setActiveCollection(ARCHIVE_SECTION);
closeSidebar();
};
const openTrashSection = () => { const openTrashSection = () => {
galleryContext.setActiveCollection(TRASH_SECTION); galleryContext.setActiveCollection(TRASH_SECTION);
closeSidebar(); closeSidebar();
}; };
const openArchiveSection = () => {
galleryContext.setActiveCollection(ARCHIVE_SECTION);
closeSidebar();
};
return ( return (
<> <>
<SidebarButton bgDark onClick={openTrashSection}> <NavigationButton
<FlexWrapper> icon={<DeleteIcon />}
<Box mr="10px"> label={constants.TRASH}
<DeleteIcon /> count={collectionSummaries.get(TRASH_SECTION)?.fileCount}
</Box> onClick={openTrashSection}
/>
{constants.TRASH} <NavigationButton
<DotSeparator /> icon={<VisibilityOffIcon />}
<Typography color="text.secondary"> label={constants.ARCHIVE}
{collectionSummaries.get(TRASH_SECTION).fileCount} count={collectionSummaries.get(ARCHIVE_SECTION)?.fileCount}
</Typography> onClick={openArchiveSection}
</FlexWrapper> />
</SidebarButton>
<SidebarButton bgDark onClick={openArchiveSection}>
<FlexWrapper>
<Box mr="10px">
<VisibilityOffIcon />
</Box>
{constants.ARCHIVE}
<DotSeparator />
<Typography color="text.secondary">
{collectionSummaries.get(ARCHIVE_SECTION).fileCount}
</Typography>
</FlexWrapper>
</SidebarButton>
</> </>
); );
} }

View file

@ -2,19 +2,20 @@ import { ToggleButton, ToggleButtonGroup } from '@mui/material';
import React from 'react'; import React from 'react';
import DarkModeIcon from '@mui/icons-material/DarkMode'; import DarkModeIcon from '@mui/icons-material/DarkMode';
import LightModeIcon from '@mui/icons-material/LightMode'; import LightModeIcon from '@mui/icons-material/LightMode';
import { THEMES } from './InfoSection'; import { THEMES } from 'types/theme';
interface Iprops { interface Iprops {
theme: THEMES; theme: THEMES;
setTheme: (theme: THEMES) => void; setTheme: (theme: THEMES) => void;
} }
export default function ThemeToggler({ theme, setTheme }: Iprops) { export default function ThemeSwitcher({ theme, setTheme }: Iprops) {
const handleChange = (event, theme: THEMES) => { const handleChange = (event, theme: THEMES) => {
setTheme(theme); if (theme !== null) {
setTheme(theme);
}
}; };
return ( return (
<ToggleButtonGroup <ToggleButtonGroup
color="primary"
size="small" size="small"
value={theme} value={theme}
exclusive exclusive

View file

@ -1,58 +1,39 @@
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext } from 'react';
import { LS_KEYS, setData } from 'utils/storage/localStorage';
import { getUserDetails } from 'services/userService';
import { UserDetails } from 'types/user';
import { getLocalUserDetails } from 'utils/user';
import InfoSection from './InfoSection';
import NavigationSection from './NavigationSection'; import NavigationSection from './NavigationSection';
import UtilitySection from './UtilitySection'; import UtilitySection from './UtilitySection';
import HelpSection from './HelpSection'; import HelpSection from './HelpSection';
import ExitSection from './ExitSection'; import ExitSection from './ExitSection';
import DebugLogs from './DebugLogs'; // import DebugLogs from './DebugLogs';
import { DrawerSidebar, DividerWithMargin } from './styledComponents'; import { DrawerSidebar, PaddedDivider } from './styledComponents';
import { AppContext } from 'pages/_app'; import { AppContext } from 'pages/_app';
import SubscriptionDetails from './SubscriptionDetails';
import HeaderSection from './Header'; import HeaderSection from './Header';
import { CollectionSummaries } from 'types/collection'; import { CollectionSummaries } from 'types/collection';
import UserDetailsSection from './userDetailsSection';
interface Iprops { interface Iprops {
collectionSummaries: CollectionSummaries; collectionSummaries: CollectionSummaries;
} }
export default function Sidebar({ collectionSummaries }: Iprops) { export default function Sidebar({ collectionSummaries }: Iprops) {
const { sidebarView, closeSidebar } = useContext(AppContext); const { sidebarView, closeSidebar } = useContext(AppContext);
const [userDetails, setUserDetails] = useState<UserDetails>(null);
useEffect(() => {
setUserDetails(getLocalUserDetails());
}, []);
useEffect(() => {
const main = async () => {
const userDetails = await getUserDetails();
setUserDetails(userDetails);
setData(LS_KEYS.USER_DETAILS, userDetails);
};
main();
}, [sidebarView]);
return ( return (
<DrawerSidebar anchor="left" open={sidebarView} onClose={closeSidebar}> <DrawerSidebar open={sidebarView} onClose={closeSidebar}>
<HeaderSection closeSidebar={closeSidebar} /> <HeaderSection closeSidebar={closeSidebar} />
<DividerWithMargin /> <PaddedDivider spaced />
<InfoSection userDetails={userDetails} /> <UserDetailsSection sidebarView={sidebarView} />
<SubscriptionDetails userDetails={userDetails} /> <PaddedDivider invisible />
<DividerWithMargin />
<NavigationSection <NavigationSection
closeSidebar={closeSidebar} closeSidebar={closeSidebar}
collectionSummaries={collectionSummaries} collectionSummaries={collectionSummaries}
/> />
<UtilitySection closeSidebar={closeSidebar} /> <UtilitySection closeSidebar={closeSidebar} />
<DividerWithMargin /> <PaddedDivider />
<HelpSection userDetails={userDetails} /> <HelpSection />
<DividerWithMargin /> <PaddedDivider />
<ExitSection /> <ExitSection />
<DividerWithMargin /> {/* <PaddedDivider />
<DebugLogs /> <DebugLogs /> */}
</DrawerSidebar> </DrawerSidebar>
); );
} }

View file

@ -1,14 +1,30 @@
import { Drawer, Divider } from '@mui/material'; import { Drawer, Divider, styled } from '@mui/material';
import { default as MuiStyled } from '@mui/styled-engine'; import { default as MuiStyled } from '@mui/styled-engine';
import CircleIcon from '@mui/icons-material/Circle';
export const DrawerSidebar = MuiStyled(Drawer)(() => ({ export const DrawerSidebar = MuiStyled(Drawer)(({ theme }) => ({
'& .MuiPaper-root': { '& .MuiPaper-root': {
width: '320px', width: '320px',
padding: '20px', padding: theme.spacing(2, 1, 4, 1),
}, },
})); }));
export const DividerWithMargin = MuiStyled(Divider)(() => ({ DrawerSidebar.defaultProps = { anchor: 'left' };
marginTop: '20px',
marginBottom: '20px', export const PaddedDivider = MuiStyled(Divider)<{
invisible?: boolean;
spaced?: boolean;
}>(({ theme, invisible, spaced }) => ({
margin: theme.spacing(spaced ? 2 : 1, 0),
opacity: invisible ? 0 : 1,
})); }));
export const DotSeparator = styled(CircleIcon)`
height: 4px;
width: 4px;
left: 86px;
top: 18px;
border-radius: 0px;
margin: 0 ${({ theme }) => theme.spacing(1)};
color: ${({ theme }) => theme.palette.text.secondary};
`;

View file

@ -0,0 +1,40 @@
import React, { useEffect } from 'react';
import { SpaceBetweenFlex } from 'components/Container';
import { PaddedDivider } from './styledComponents';
import SubscriptionDetails from './SubscriptionDetails';
import { getUserDetails } from 'services/userService';
import { UserDetails } from 'types/user';
import { LS_KEYS } from 'utils/storage/localStorage';
import { useLocalState } from 'hooks/useLocalState';
import { THEMES } from 'types/theme';
import ThemeSwitcher from './ThemeSwitcher';
import Typography from '@mui/material/Typography';
export default function UserDetailsSection({ sidebarView }) {
const [userDetails, setUserDetails] = useLocalState<UserDetails>(
LS_KEYS.USER_DETAILS
);
const [theme, setTheme] = useLocalState<THEMES>(LS_KEYS.THEME, THEMES.DARK);
useEffect(() => {
if (!sidebarView) {
return;
}
const main = async () => {
const userDetails = await getUserDetails();
setUserDetails(userDetails);
};
main();
}, [sidebarView]);
return (
<>
<SpaceBetweenFlex px={1}>
<Typography>{userDetails?.email}</Typography>
<ThemeSwitcher theme={theme} setTheme={setTheme} />
</SpaceBetweenFlex>
<PaddedDivider invisible />
<SubscriptionDetails userDetails={userDetails} />
</>
);
}

View file

@ -1,22 +0,0 @@
import React from 'react';
export default function NavigateNext(props) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height="40"
viewBox="0 0 24 24"
width="24px"
fill="currentColor"
{...props}>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
</svg>
);
}
NavigateNext.defaultProps = {
height: 24,
width: 24,
viewBox: '0 0 24 24',
};

View file

@ -1,23 +0,0 @@
import React from 'react';
export default function SortIcon(props) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height={props.height}
viewBox={props.viewBox}
width={props.width}>
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"
fill="currentColor"
/>
</svg>
);
}
SortIcon.defaultProps = {
height: 24,
width: 24,
viewBox: '0 0 24 24',
};

View file

@ -1,20 +0,0 @@
import React from 'react';
export default function TickIcon(props) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height={props.height}
viewBox={props.viewBox}
width={props.width}
fill="currentColor">
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" />
</svg>
);
}
TickIcon.defaultProps = {
height: 20,
width: 20,
viewBox: '0 0 24 24',
};

View file

@ -1,90 +0,0 @@
import React, { useState } from 'react';
import { COLLECTION_SORT_BY } from 'constants/collection';
import Menu from '@mui/material/Menu';
import { IconButton, MenuItem } from '@mui/material';
import SortIcon from 'components/icons/SortIcon';
import TickIcon from 'components/icons/TickIcon';
import constants from 'utils/strings/constants';
import { ListItemIcon, ListItemText, MenuList, Paper } from '@mui/material';
interface Props {
setCollectionSortBy: (sortBy: COLLECTION_SORT_BY) => void;
activeSortBy: COLLECTION_SORT_BY;
}
interface OptionProps extends Props {
close: () => void;
}
const SortByOptionCreator =
({ setCollectionSortBy, activeSortBy, close }: OptionProps) =>
(props: { sortBy: COLLECTION_SORT_BY; children: any }) => {
const handleClick = () => {
setCollectionSortBy(props.sortBy);
close();
};
return (
<MenuItem onClick={handleClick}>
<ListItemIcon
sx={{
minWidth: '30px',
}}>
{activeSortBy === props.sortBy && <TickIcon />}
</ListItemIcon>
<ListItemText>{props.children}</ListItemText>
</MenuItem>
);
};
const CollectionSortOptions = (props: OptionProps) => {
const SortByOption = SortByOptionCreator(props);
return (
<Paper sx={{ maxWidth: '100%' }}>
<MenuList>
<SortByOption sortBy={COLLECTION_SORT_BY.NAME}>
{constants.SORT_BY_NAME}
</SortByOption>
<SortByOption
sortBy={COLLECTION_SORT_BY.CREATION_TIME_DESCENDING}>
{constants.SORT_BY_CREATION_TIME_DESCENDING}
</SortByOption>
<SortByOption
sortBy={COLLECTION_SORT_BY.CREATION_TIME_ASCENDING}>
{constants.SORT_BY_CREATION_TIME_ASCENDING}
</SortByOption>
<SortByOption
sortBy={COLLECTION_SORT_BY.UPDATION_TIME_DESCENDING}>
{constants.SORT_BY_UPDATION_TIME_DESCENDING}
</SortByOption>
</MenuList>
</Paper>
);
};
export default function CollectionSort(props: Props) {
const [sortByEl, setSortByEl] = useState(null);
const handleClose = () => setSortByEl(null);
return (
<>
<IconButton
onClick={(event) => setSortByEl(event.currentTarget)}
aria-controls={sortByEl ? 'collection-sort' : undefined}
aria-haspopup="true"
aria-expanded={sortByEl ? 'true' : undefined}>
<SortIcon />
</IconButton>
<Menu
id="collection-sort"
anchorEl={sortByEl}
open={Boolean(sortByEl)}
onClose={handleClose}
MenuListProps={{
'aria-labelledby': 'collection-sort',
}}>
<CollectionSortOptions {...props} close={handleClose} />
</Menu>
</>
);
}

View file

@ -1,62 +0,0 @@
import { createTheme } from '@mui/material/styles';
declare module '@mui/material/styles' {
interface Palette {
accent: Palette['primary'];
danger: Palette['primary'];
}
interface PaletteOptions {
accent: PaletteOptions['primary'];
danger: PaletteOptions['primary'];
}
}
declare module '@mui/material/Button' {
export interface ButtonPropsColorOverrides {
danger: true;
}
}
// Create a theme instance.
const darkThemeOptions = createTheme({
components: {
MuiPaper: {
styleOverrides: { root: { backgroundImage: 'none' } },
},
MuiLink: {
styleOverrides: {
root: {
color: '#fff',
textDecoration: 'none',
'&:hover': {
color: '#fff',
textDecoration: 'underline',
textDecorationColor: '#fff',
},
},
},
},
},
palette: {
mode: 'dark',
primary: {
main: '#fff',
},
text: {
primary: 'hsla(0, 0%, 100%, 1)',
secondary: 'hsla(0, 0%, 100%, 0.5)',
},
accent: {
main: '#43BA6C',
dark: '#369556',
},
danger: {
main: '#c93f3f',
},
background: { default: '#191919', paper: '#191919' },
},
});
export default darkThemeOptions;

View file

@ -1,4 +1,4 @@
import { SCROLL_DIRECTION } from 'components/Collections/NavigationButton'; import { SCROLL_DIRECTION } from 'components/Collections/CollectionBar/NavigationButton';
import { useRef, useState, useEffect } from 'react'; import { useRef, useState, useEffect } from 'react';
export default function useComponentScroll({ export default function useComponentScroll({
@ -15,14 +15,17 @@ export default function useComponentScroll({
}>({}); }>({});
const updateScrollObj = () => { const updateScrollObj = () => {
if (componentRef.current) { if (!componentRef.current) {
const { scrollLeft, scrollWidth, clientWidth } = return;
componentRef.current;
setScrollObj({ scrollLeft, scrollWidth, clientWidth });
} }
const { scrollLeft, scrollWidth, clientWidth } = componentRef.current;
setScrollObj({ scrollLeft, scrollWidth, clientWidth });
}; };
useEffect(() => { useEffect(() => {
if (!componentRef.current) {
return;
}
// Add event listener // Add event listener
componentRef.current?.addEventListener('scroll', updateScrollObj); componentRef.current?.addEventListener('scroll', updateScrollObj);

View file

@ -24,9 +24,11 @@ import MessageDialog, {
SetDialogMessage, SetDialogMessage,
} from 'components/MessageDialog'; } from 'components/MessageDialog';
import { ThemeProvider as MThemeProvider } from '@mui/material/styles'; import { ThemeProvider as MThemeProvider } from '@mui/material/styles';
import darkThemeOptions from 'darkThemeOptions'; import darkThemeOptions from 'themes/darkThemeOptions';
import { CssBaseline } from '@mui/material'; import { CssBaseline } from '@mui/material';
import SidebarToggler from 'components/Navbar/SidebarToggler'; import SidebarToggler from 'components/Navbar/SidebarToggler';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import * as types from 'styled-components/cssprop';
export const LogoImage = styled.img` export const LogoImage = styled.img`
max-height: 28px; max-height: 28px;

View file

@ -0,0 +1,96 @@
import {
createTheme,
PaletteColor,
PaletteColorOptions,
} from '@mui/material/styles';
declare module '@mui/material/styles' {
interface Palette {
accent: PaletteColor;
danger: PaletteColor;
}
interface PaletteOptions {
accent?: PaletteColorOptions;
danger?: PaletteColorOptions;
}
}
declare module '@mui/material/Button' {
export interface ButtonPropsColorOverrides {
accent: true;
danger: true;
}
}
declare module '@mui/material/ToggleButtonGroup' {
export interface ToggleButtonGroupPropsColorOverrides {
negative: true;
}
}
// Create a theme instance.
const darkThemeOptions = createTheme({
components: {
MuiPaper: {
styleOverrides: { root: { backgroundImage: 'none' } },
},
MuiLink: {
styleOverrides: {
root: {
textDecoration: 'none',
'&:hover': {
textDecoration: 'underline',
},
},
},
},
MuiMenu: {
styleOverrides: { paper: { margin: '10px' } },
},
MuiButton: {
styleOverrides: {
root: {
fontSize: '18px',
lineHeight: '21.78px',
padding: '16px',
textTransform: 'none',
borderRadius: '8px',
},
},
},
},
palette: {
mode: 'dark',
primary: {
main: '#f0f0f0',
},
secondary: {
main: 'rgba(256, 256, 256, 0.12)',
contrastText: '#fff',
},
text: {
primary: '#fff',
secondary: '#808080',
},
accent: {
main: '#43BA6C',
dark: '#369556',
},
danger: {
main: '#c93f3f',
},
background: { default: '#000000', paper: '#1b1b1b' },
grey: {
A100: '#ccc',
A200: 'rgba(256, 256, 256, 0.24)',
},
divider: 'rgba(255, 255, 255, 0.24)',
},
shape: {
borderRadius: 8,
},
});
export default darkThemeOptions;

4
src/types/theme/index.ts Normal file
View file

@ -0,0 +1,4 @@
export enum THEMES {
LIGHT,
DARK,
}

View file

@ -18,6 +18,7 @@ export enum LS_KEYS {
LOGS = 'logs', LOGS = 'logs',
USER_DETAILS = 'userDetails', USER_DETAILS = 'userDetails',
COLLECTION_SORT_BY = 'collectionSortBy', COLLECTION_SORT_BY = 'collectionSortBy',
THEME = 'theme',
} }
export const setData = (key: LS_KEYS, value: object) => { export const setData = (key: LS_KEYS, value: object) => {

View file

@ -32,6 +32,7 @@ const Trigger = styled.span`
`; `;
const englishConstants = { const englishConstants = {
ENTE: 'ente',
HERO_HEADER: () => ( HERO_HEADER: () => (
<div> <div>
with <Logo src="/icon.svg" /> with <Logo src="/icon.svg" />
@ -718,7 +719,6 @@ const englishConstants = {
VIEW_ALL_ALBUMS: 'View all Albums', VIEW_ALL_ALBUMS: 'View all Albums',
ALL_ALBUMS: 'All Albums', ALL_ALBUMS: 'All Albums',
PHOTOS: 'Photos', PHOTOS: 'Photos',
ENTE: 'ente',
ENDS: 'Ends', ENDS: 'Ends',
}; };

View file

@ -1634,10 +1634,10 @@
resolved "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz" resolved "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz"
integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==
"@types/styled-components@^5.1.3": "@types/styled-components@^5.1.25":
version "5.1.14" version "5.1.25"
resolved "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.14.tgz" resolved "https://registry.yarnpkg.com/@types/styled-components/-/styled-components-5.1.25.tgz#0177c4ab5fa7c6ed0565d36f597393dae3f380ad"
integrity sha512-d6P1/tyNytqKwam3cQXq7a9uPtovc/mdAs7dBiz1YbDdNIT3X4WmuFU78YdSYh84TXVuhOwezZ3EeKuNBhwsHQ== integrity sha512-fgwl+0Pa8pdkwXRoVPP9JbqF0Ivo9llnmsm+7TCI330kbPIFd9qv1Lrhr37shf4tnxCOSu+/IgqM7uJXLWZZNQ==
dependencies: dependencies:
"@types/hoist-non-react-statics" "*" "@types/hoist-non-react-statics" "*"
"@types/react" "*" "@types/react" "*"