refactoring and style updates

This commit is contained in:
Abhinav 2022-04-24 00:05:24 +05:30
parent 9ca78c9bc2
commit 40777d109a
11 changed files with 277 additions and 205 deletions

View file

@ -55,10 +55,8 @@ export const Value = styled.div<{ width?: string }>`
`;
export const FlexWrapper = styled.div`
width: 100%;
display: flex;
text-align: center;
justify-content: center;
flex-wrap: wrap;
`;
export const FreeFlowText = styled.div`
@ -66,3 +64,9 @@ export const FreeFlowText = styled.div`
min-width: 30%;
text-align: left;
`;
export const TwoScreenSpacedOptions = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`;

View file

@ -0,0 +1,37 @@
import React from 'react';
import { GalleryContext } from 'pages/gallery';
import { useState, useContext, useEffect } from 'react';
import downloadManager from 'services/downloadManager';
import { EnteFile } from 'types/file';
import { CollectionTile } from '.';
export default function CollectionCard(props: {
children?: any;
latestFile: EnteFile;
onClick: () => void;
customCollectionTile?: any;
}) {
const { latestFile: file, onClick, children, customCollectionTile } = props;
const [coverImageURL, setCoverImageURL] = useState(null);
const galleryContext = useContext(GalleryContext);
useEffect(() => {
const main = async () => {
if (!file) {
return;
}
if (!galleryContext.thumbs.has(file.id)) {
const url = await downloadManager.getThumbnail(file);
galleryContext.thumbs.set(file.id, url);
}
setCoverImageURL(galleryContext.thumbs.get(file.id));
};
main();
}, [file]);
const UsedCollectionTile = customCollectionTile ?? CollectionTile;
return (
<UsedCollectionTile coverImgURL={coverImageURL} onClick={onClick}>
{children}
</UsedCollectionTile>
);
}

View file

@ -0,0 +1,27 @@
import React from 'react';
import { EnteFile } from 'types/file';
import { CollectionTileWrapper, ActiveIndicator } from '.';
import CollectionCard from './CollectionCard';
const CollectionCardWithActiveIndicator = React.forwardRef(
(
props: {
children;
active: boolean;
latestFile: EnteFile;
onClick: () => void;
},
ref: any
) => {
const { active, ...others } = props;
return (
<CollectionTileWrapper ref={ref}>
<CollectionCard {...others} />
{active && <ActiveIndicator />}
</CollectionTileWrapper>
);
}
);
export default CollectionCardWithActiveIndicator;

View file

@ -1,3 +1,4 @@
import { TwoScreenSpacedOptions } from 'components/Container';
import { IMAGE_CONTAINER_MAX_WIDTH } from 'constants/gallery';
import styled from 'styled-components';
@ -11,10 +12,9 @@ export const CollectionBarWrapper = styled.div`
border-bottom: 1px solid ${({ theme }) => theme.palette.grey.A400};
`;
export const Header = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
export const TwoScreenSpacedOptionsWithBodyPadding = styled(
TwoScreenSpacedOptions
)`
margin-bottom: 8px;
margin-top: 16px;
padding: 0 24px;
@ -39,7 +39,9 @@ export const ScrollContainer = styled.div`
display: flex;
`;
export const EmptyCollectionTile = styled.div`
export const CollectionTile = styled.div<{
coverImgURL?: string;
}>`
flex-shrink: 0;
display: flex;
width: 80px;
@ -47,15 +49,9 @@ export const EmptyCollectionTile = styled.div`
border-radius: 4px;
padding: 4px 6px;
align-items: flex-end;
border: 1px dashed ${({ theme }) => theme.palette.grey.A200};
justify-content: space-between;
user-select: none;
cursor: pointer;
`;
export const CollectionTile = styled(EmptyCollectionTile)<{
coverImgURL: string;
}>`
background-image: url(${({ coverImgURL }) => coverImgURL});
background-size: cover;
border: none;

View file

@ -8,7 +8,10 @@ export default function SortIcon(props) {
viewBox={props.viewBox}
width={props.width}>
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z" />
<path
d="M3 18h6v-2H3v2zM3 6v2h18V6H3zm0 7h12v-2H3v2z"
fill="currentColor"
/>
</svg>
);
}

View file

@ -0,0 +1,149 @@
import NavigationButton, {
SCROLL_DIRECTION,
} from 'components/NavigationButton';
import React, { useEffect, useRef, useState } from 'react';
import { Collection, CollectionSummaries } from 'types/collection';
import constants from 'utils/strings/constants';
import { ALL_SECTION } from 'constants/collection';
import { Link, Typography } from '@mui/material';
import {
Hider,
CollectionBarWrapper,
CollectionWithNavigationContainer,
ScrollContainer,
TwoScreenSpacedOptionsWithBodyPadding,
CollectionTile,
} from 'components/collection';
import CollectionCardWithActiveIndicator from 'components/collection/CollectionCardWithActiveIndicator';
import styled from 'styled-components';
interface IProps {
collections: Collection[];
activeCollection?: number;
setActiveCollection: (id?: number) => void;
isInSearchMode: boolean;
collectionSummaries: CollectionSummaries;
showAllCollections: () => void;
}
const CollectionTitleWithDashedBorder = styled(CollectionTile)`
border: 1px dashed ${({ theme }) => theme.palette.grey.A200};
`;
const CreateNewCollectionTile = () => {
return (
<CollectionTitleWithDashedBorder>
<div>{constants.NEW} </div>
<div>{'+'}</div>
</CollectionTitleWithDashedBorder>
);
};
export default function CollectionBar(props: IProps) {
const {
activeCollection,
collections,
setActiveCollection,
collectionSummaries,
showAllCollections,
} = props;
const collectionWrapperRef = useRef<HTMLDivElement>(null);
const collectionChipsRef = props.collections.reduce(
(refMap, collection) => {
refMap[collection.id] = React.createRef();
return refMap;
},
{}
);
const [scrollObj, setScrollObj] = useState<{
scrollLeft?: number;
scrollWidth?: number;
clientWidth?: number;
}>({});
const updateScrollObj = () => {
if (collectionWrapperRef.current) {
const { scrollLeft, scrollWidth, clientWidth } =
collectionWrapperRef.current;
setScrollObj({ scrollLeft, scrollWidth, clientWidth });
}
};
useEffect(() => {
updateScrollObj();
}, [collectionWrapperRef.current, props.isInSearchMode, collections]);
useEffect(() => {
if (!collectionWrapperRef?.current) {
return;
}
collectionWrapperRef.current.scrollLeft = 0;
}, [collections]);
useEffect(() => {
collectionChipsRef[activeCollection]?.current.scrollIntoView({
inline: 'center',
});
}, [activeCollection]);
const clickHandler = (collectionID?: number) => () => {
setActiveCollection(collectionID ?? ALL_SECTION);
};
const scrollCollection = (direction: SCROLL_DIRECTION) => () => {
collectionWrapperRef.current.scrollBy(250 * direction, 0);
};
return (
<Hider hide={props.isInSearchMode}>
<TwoScreenSpacedOptionsWithBodyPadding>
<Typography>{constants.ALBUMS}</Typography>
{scrollObj.scrollWidth > scrollObj.clientWidth && (
<Link component="button" onClick={showAllCollections}>
{constants.VIEW_ALL_ALBUMS}
</Link>
)}
</TwoScreenSpacedOptionsWithBodyPadding>
<CollectionBarWrapper>
<CollectionWithNavigationContainer>
{scrollObj.scrollLeft > 0 && (
<NavigationButton
scrollDirection={SCROLL_DIRECTION.LEFT}
onClick={scrollCollection(SCROLL_DIRECTION.LEFT)}
/>
)}
<ScrollContainer
ref={collectionWrapperRef}
onScroll={updateScrollObj}>
<CollectionCardWithActiveIndicator
latestFile={null}
active={activeCollection === ALL_SECTION}
onClick={clickHandler(ALL_SECTION)}>
{constants.ALL_SECTION_NAME}
</CollectionCardWithActiveIndicator>
{collections.map((item) => (
<CollectionCardWithActiveIndicator
key={item.id}
latestFile={
collectionSummaries.get(item.id)?.latestFile
}
ref={collectionChipsRef[item.id]}
active={activeCollection === item.id}
onClick={clickHandler(item.id)}>
{item.name}
</CollectionCardWithActiveIndicator>
))}
<CreateNewCollectionTile />
</ScrollContainer>
{scrollObj.scrollLeft <
scrollObj.scrollWidth - scrollObj.clientWidth && (
<NavigationButton
scrollDirection={SCROLL_DIRECTION.RIGHT}
onClick={scrollCollection(SCROLL_DIRECTION.RIGHT)}
/>
)}
</CollectionWithNavigationContainer>
</CollectionBarWrapper>
</Hider>
);
}

View file

@ -1,196 +1,41 @@
import NavigationButton, {
SCROLL_DIRECTION,
} from 'components/NavigationButton';
import React, { useContext, useEffect, useRef, useState } from 'react';
import { Collection, CollectionSummaries } from 'types/collection';
import constants from 'utils/strings/constants';
import { ALL_SECTION } from 'constants/collection';
import { Link, Typography } from '@mui/material';
import {
CollectionTileWrapper,
CollectionTile,
ActiveIndicator,
Hider,
CollectionBarWrapper,
Header,
CollectionWithNavigationContainer,
ScrollContainer,
EmptyCollectionTile,
} from 'components/collection';
import { GalleryContext } from 'pages/gallery';
import downloadManager from 'services/downloadManager';
import { EnteFile } from 'types/file';
interface CollectionProps {
import CollectionBar from './CollectionBar';
import React, { useState } from 'react';
import AllCollections from 'components/collection/AllCollections';
interface Iprops {
collections: Collection[];
activeCollection?: number;
setActiveCollection: (id?: number) => void;
isInSearchMode: boolean;
collectionSummaries: CollectionSummaries;
}
const CollectionTileWithActiveIndicator = React.forwardRef(
(
props: {
children;
active: boolean;
latestFile: EnteFile;
onClick: () => void;
},
ref: any
) => {
const [coverImageURL, setCoverImageURL] = useState(null);
const galleryContext = useContext(GalleryContext);
const { latestFile: file, onClick, active, children } = props;
useEffect(() => {
const main = async () => {
if (!file) {
return;
}
if (!galleryContext.thumbs.has(file.id)) {
const url = await downloadManager.getThumbnail(file);
galleryContext.thumbs.set(file.id, url);
}
setCoverImageURL(galleryContext.thumbs.get(file.id));
};
main();
}, [file]);
return (
<CollectionTileWrapper ref={ref}>
<CollectionTile coverImgURL={coverImageURL} onClick={onClick}>
{children}
</CollectionTile>
{active && <ActiveIndicator />}
</CollectionTileWrapper>
);
}
);
const CreateNewCollectionHookTile = () => {
return (
<EmptyCollectionTile>
<div>{constants.NEW} </div>
<div>{'+'}</div>
</EmptyCollectionTile>
);
};
export default function CollectionBar(props: CollectionProps) {
export function Collections(props: Iprops) {
const {
activeCollection,
collections,
isInSearchMode,
activeCollection,
setActiveCollection,
collectionSummaries,
} = props;
const collectionWrapperRef = useRef<HTMLDivElement>(null);
const collectionChipsRef = props.collections.reduce(
(refMap, collection) => {
refMap[collection.id] = React.createRef();
return refMap;
},
{}
);
const [scrollObj, setScrollObj] = useState<{
scrollLeft?: number;
scrollWidth?: number;
clientWidth?: number;
}>({});
const updateScrollObj = () => {
if (collectionWrapperRef.current) {
const { scrollLeft, scrollWidth, clientWidth } =
collectionWrapperRef.current;
setScrollObj({ scrollLeft, scrollWidth, clientWidth });
}
};
useEffect(() => {
updateScrollObj();
}, [collectionWrapperRef.current, props.isInSearchMode, collections]);
useEffect(() => {
if (!collectionWrapperRef?.current) {
return;
}
collectionWrapperRef.current.scrollLeft = 0;
}, [collections]);
useEffect(() => {
collectionChipsRef[activeCollection]?.current.scrollIntoView({
inline: 'center',
});
}, [activeCollection]);
const clickHandler = (collectionID?: number) => () => {
setActiveCollection(collectionID ?? ALL_SECTION);
};
const scrollCollection = (direction: SCROLL_DIRECTION) => () => {
collectionWrapperRef.current.scrollBy(250 * direction, 0);
};
const [allCollectionView, setAllCollectionView] = useState(false);
return (
<Hider hide={props.isInSearchMode}>
<Header>
<Typography>{constants.ALBUMS}</Typography>
{scrollObj.scrollWidth > scrollObj.clientWidth && (
<Link component="button">{constants.ALL_ALBUMS}</Link>
)}
</Header>
<CollectionBarWrapper>
<CollectionWithNavigationContainer>
{scrollObj.scrollLeft > 0 && (
<NavigationButton
scrollDirection={SCROLL_DIRECTION.LEFT}
onClick={scrollCollection(SCROLL_DIRECTION.LEFT)}
/>
)}
<ScrollContainer
ref={collectionWrapperRef}
onScroll={updateScrollObj}>
<CollectionTileWithActiveIndicator
latestFile={null}
active={activeCollection === ALL_SECTION}
onClick={clickHandler(ALL_SECTION)}>
{constants.ALL_SECTION_NAME}
</CollectionTileWithActiveIndicator>
{[
...collections,
...collections,
...collections,
...collections,
...collections,
...collections,
...collections,
...collections,
...collections,
...collections,
...collections,
...collections,
].map((item) => (
<CollectionTileWithActiveIndicator
key={item.id}
latestFile={
collectionSummaries.get(item.id)?.latestFile
}
ref={collectionChipsRef[item.id]}
active={activeCollection === item.id}
onClick={clickHandler(item.id)}>
{item.name}
</CollectionTileWithActiveIndicator>
))}
<CreateNewCollectionHookTile />
</ScrollContainer>
{scrollObj.scrollLeft <
scrollObj.scrollWidth - scrollObj.clientWidth && (
<NavigationButton
scrollDirection={SCROLL_DIRECTION.RIGHT}
onClick={scrollCollection(SCROLL_DIRECTION.RIGHT)}
/>
)}
</CollectionWithNavigationContainer>
</CollectionBarWrapper>
</Hider>
<>
<CollectionBar
collections={collections}
isInSearchMode={isInSearchMode}
activeCollection={activeCollection}
setActiveCollection={setActiveCollection}
collectionSummaries={collectionSummaries}
showAllCollections={() => setAllCollectionView(true)}
/>
<AllCollections
isOpen={allCollectionView}
close={() => setAllCollectionView(false)}
collectionSummaries={collectionSummaries}
setActiveCollection={setActiveCollection}
/>
</>
);
}

View file

@ -1,11 +1,19 @@
import React from 'react';
import { Typography } from '@mui/material';
import constants from 'utils/strings/constants';
import { Header } from 'components/collection';
import { IconButton } from 'components/Container';
import OptionIcon from 'components/icons/OptionIcon-2';
import { CollectionSummary } from 'types/collection';
import { TwoScreenSpacedOptionsWithBodyPadding } from 'components/collection';
import styled from 'styled-components';
const InvertedIconButton = styled(IconButton)`
background-color: ${({ theme }) => theme.palette.primary.main};
color: ${({ theme }) => theme.palette.background.default};
&:hover {
background-color: ${({ theme }) => theme.palette.grey.A100};
}
`;
interface Iprops {
collectionSummary: CollectionSummary;
}
@ -16,7 +24,7 @@ export default function collectionInfo(props: Iprops) {
}
return (
<Header>
<TwoScreenSpacedOptionsWithBodyPadding>
<div>
<Typography variant="h5">
<strong>{collectionSummary.collectionName}</strong>
@ -25,9 +33,12 @@ export default function collectionInfo(props: Iprops) {
{collectionSummary.fileCount} {constants.PHOTOS}
</Typography>
</div>
<IconButton style={{ transform: 'rotate(90deg)' }}>
<InvertedIconButton
style={{
transform: 'rotate(90deg)',
}}>
<OptionIcon />
</IconButton>
</Header>
</InvertedIconButton>
</TwoScreenSpacedOptionsWithBodyPadding>
);
}

View file

@ -11,8 +11,9 @@ const darkThemeOptions = createTheme({
primary: '#fff',
secondary: '#777',
},
background: { default: '#191919', paper: '#202020' },
background: { default: '#191919', paper: '#191919' },
grey: {
A100: '#ccc',
A200: '#777',
A400: '#4E4E4E',
},

View file

@ -358,9 +358,7 @@ a:hover {
text-decoration: none;
background-color: #e9ecef;
}
hr{
border-top: 1rem solid #444 !important;
}
.list-group-item:hover{
background-color:#343434 !important;
}

View file

@ -714,7 +714,8 @@ const englishConstants = {
YES_STOP_UPLOADS: 'yes, stop uploads',
ALBUMS: 'Albums',
NEW: 'New',
ALL_ALBUMS: 'View all Albums',
VIEW_ALL_ALBUMS: 'View all Albums',
ALL_ALBUMS: 'All Albums',
PHOTOS: 'Photos',
};