Merge branch 'ui-redesign' into sidebar-items-redesign
This commit is contained in:
commit
e70011b55f
|
@ -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",
|
||||||
|
|
|
@ -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`
|
||||||
|
|
|
@ -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>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
37
src/components/Collections/AllCollections/CollectionCard.tsx
Normal file
37
src/components/Collections/AllCollections/CollectionCard.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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;
|
|
@ -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>
|
||||||
|
);
|
||||||
|
}
|
30
src/components/Collections/AllCollections/content.tsx
Normal file
30
src/components/Collections/AllCollections/content.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
46
src/components/Collections/AllCollections/header.tsx
Normal file
46
src/components/Collections/AllCollections/header.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
67
src/components/Collections/AllCollections/index.tsx
Normal file
67
src/components/Collections/AllCollections/index.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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(
|
||||||
(
|
(
|
|
@ -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 (
|
|
@ -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;
|
|
@ -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';
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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={{
|
||||||
|
|
|
@ -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' }}>
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)`
|
||||||
|
|
|
@ -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};
|
||||||
|
|
26
src/components/MessageDialog/TitleWithCloseButton.tsx
Normal file
26
src/components/MessageDialog/TitleWithCloseButton.tsx
Normal 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;
|
|
@ -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,
|
|
@ -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';
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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>
|
|
||||||
);
|
|
||||||
}
|
|
40
src/components/Sidebar/NavigationButton.tsx
Normal file
40
src/components/Sidebar/NavigationButton.tsx
Normal 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;
|
|
@ -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>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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};
|
||||||
|
`;
|
||||||
|
|
40
src/components/Sidebar/userDetailsSection.tsx
Normal file
40
src/components/Sidebar/userDetailsSection.tsx
Normal 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} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -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',
|
|
||||||
};
|
|
|
@ -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',
|
|
||||||
};
|
|
|
@ -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',
|
|
||||||
};
|
|
|
@ -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>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -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;
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
96
src/themes/darkThemeOptions.tsx
Normal file
96
src/themes/darkThemeOptions.tsx
Normal 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
4
src/types/theme/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export enum THEMES {
|
||||||
|
LIGHT,
|
||||||
|
DARK,
|
||||||
|
}
|
|
@ -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) => {
|
||||||
|
|
|
@ -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',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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" "*"
|
||||||
|
|
Loading…
Reference in a new issue