Merge pull request #623 from ente-io/collection-bar-tile-redesign

Collection bar tile redesign
This commit is contained in:
Abhinav Kumar 2022-06-28 15:42:09 +05:30 committed by GitHub
commit 4f92c342d6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 130 additions and 63 deletions

View file

@ -1,10 +1,20 @@
import { Typography } from '@mui/material'; import { Box, Typography } from '@mui/material';
import { FlexWrapper } from 'components/Container';
import React from 'react'; import React from 'react';
import constants from 'utils/strings/constants'; import constants from 'utils/strings/constants';
export function CollectionInfo({ name, fileCount }) { interface Iprops {
name: string;
fileCount: number;
endIcon?: React.ReactNode;
}
export function CollectionInfo({ name, fileCount, endIcon }: Iprops) {
return ( return (
<div> <div>
<FlexWrapper>
<Typography variant="subtitle">{name}</Typography> <Typography variant="subtitle">{name}</Typography>
{endIcon && <Box ml={1.5}>{endIcon}</Box>}
</FlexWrapper>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
{constants.PHOTO_COUNT(fileCount)} {constants.PHOTO_COUNT(fileCount)}
</Typography> </Typography>

View file

@ -5,7 +5,11 @@ import CollectionOptions from 'components/Collections/CollectionOptions';
import { SetCollectionNamerAttributes } from 'components/Collections/CollectionNamer'; import { SetCollectionNamerAttributes } from 'components/Collections/CollectionNamer';
import { SpaceBetweenFlex } from 'components/Container'; import { SpaceBetweenFlex } from 'components/Container';
import { CollectionInfoBarWrapper } from './styledComponents'; import { CollectionInfoBarWrapper } from './styledComponents';
import { isOptionsHavingCollection } from 'utils/collection'; import { shouldShowOptions } from 'utils/collection';
import { CollectionSummaryType } from 'constants/collection';
import Favorite from '@mui/icons-material/Favorite';
import VisibilityOff from '@mui/icons-material/VisibilityOff';
import Delete from '@mui/icons-material/Delete';
interface Iprops { interface Iprops {
activeCollection: Collection; activeCollection: Collection;
@ -33,13 +37,28 @@ export default function CollectionInfoWithOptions({
const { name, type, fileCount } = collectionSummary; const { name, type, fileCount } = collectionSummary;
const EndIcon = ({ type }: { type: CollectionSummaryType }) => {
switch (type) {
case CollectionSummaryType.favorites:
return <Favorite />;
case CollectionSummaryType.archived:
case CollectionSummaryType.archive:
return <VisibilityOff />;
case CollectionSummaryType.trash:
return <Delete />;
default:
return <></>;
}
};
return ( return (
<CollectionInfoBarWrapper> <CollectionInfoBarWrapper>
<SpaceBetweenFlex> <SpaceBetweenFlex>
<CollectionInfo name={name} fileCount={fileCount} /> <CollectionInfo
{isOptionsHavingCollection(type) && ( name={name}
<CollectionOptions {...props} /> fileCount={fileCount}
)} endIcon={<EndIcon type={type} />}
/>
{shouldShowOptions(type) && <CollectionOptions {...props} />}
</SpaceBetweenFlex> </SpaceBetweenFlex>
</CollectionInfoBarWrapper> </CollectionInfoBarWrapper>
); );

View file

@ -3,28 +3,32 @@ import { EnteFile } from 'types/file';
import { import {
ActiveIndicator, ActiveIndicator,
CollectionBarTile, CollectionBarTile,
CollectionBarTileIcon,
CollectionBarTileText, CollectionBarTileText,
} from '../styledComponents'; } from '../styledComponents';
import CollectionCard from '../CollectionCard'; import CollectionCard from '../CollectionCard';
import TruncateText from 'components/TruncateText'; import TruncateText from 'components/TruncateText';
import { Box } from '@mui/material'; import { Box } from '@mui/material';
import { CollectionSummaryType } from 'constants/collection';
import Favorite from '@mui/icons-material/Favorite';
import VisibilityOff from '@mui/icons-material/VisibilityOff';
interface Iprops { interface Iprops {
active: boolean; active: boolean;
latestFile: EnteFile; latestFile: EnteFile;
collectionName: string; collectionName: string;
collectionType: CollectionSummaryType;
onClick: () => void; onClick: () => void;
} }
const CollectionListBarCard = React.forwardRef((props: Iprops, ref: any) => { const CollectionListBarCard = React.forwardRef((props: Iprops, ref: any) => {
const { active, collectionName, ...others } = props; const { active, collectionName, collectionType, ...others } = props;
return ( return (
<Box ref={ref}> <Box ref={ref}>
<CollectionCard collectionTile={CollectionBarTile} {...others}> <CollectionCard collectionTile={CollectionBarTile} {...others}>
<CollectionBarTileText> <CollectionCardText collectionName={collectionName} />
<TruncateText text={collectionName} /> <CollectionCardIcon collectionType={collectionType} />
</CollectionBarTileText>
</CollectionCard> </CollectionCard>
{active && <ActiveIndicator />} {active && <ActiveIndicator />}
</Box> </Box>
@ -32,3 +36,22 @@ const CollectionListBarCard = React.forwardRef((props: Iprops, ref: any) => {
}); });
export default CollectionListBarCard; export default CollectionListBarCard;
function CollectionCardText({ collectionName }) {
return (
<CollectionBarTileText>
<TruncateText text={collectionName} />
</CollectionBarTileText>
);
}
function CollectionCardIcon({ collectionType }) {
return (
<CollectionBarTileIcon>
{collectionType === CollectionSummaryType.favorites && <Favorite />}
{collectionType === CollectionSummaryType.archived && (
<VisibilityOff />
)}
</CollectionBarTileIcon>
);
}

View file

@ -99,6 +99,7 @@ export default function CollectionListBar(props: IProps) {
ref={collectionChipsRef[item.id]} ref={collectionChipsRef[item.id]}
active={activeCollection === item.id} active={activeCollection === item.id}
onClick={clickHandler(item.id)} onClick={clickHandler(item.id)}
collectionType={item.type}
collectionName={item.name} collectionName={item.name}
/> />
))} ))}

View file

@ -82,12 +82,20 @@ export const ResultPreviewTile = styled(CollectionTile)`
export const CollectionBarTileText = styled(Overlay)` export const CollectionBarTileText = styled(Overlay)`
padding: 4px; padding: 4px;
background: linear-gradient( background: linear-gradient(
180deg, 0deg,
rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.1) 0%,
rgba(0, 0, 0, 0.5) 86.46% rgba(0, 0, 0, 0.5) 86.46%
); );
`;
export const CollectionBarTileIcon = styled(Overlay)`
padding: 4px;
display: flex; display: flex;
justify-content: flex-end;
align-items: flex-end; align-items: flex-end;
& > .MuiSvgIcon-root {
font-size: 20px;
}
`; `;
export const AllCollectionTileText = styled(Overlay)` export const AllCollectionTileText = styled(Overlay)`

View file

@ -1,16 +1,16 @@
import Tooltip from '@mui/material/Tooltip'; import Tooltip from '@mui/material/Tooltip';
import React from 'react'; import React from 'react';
import { styled, Typography } from '@mui/material'; import { Box, Typography } from '@mui/material';
export const EllipseText = styled(Typography)`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
export default function TruncateText({ text }) { export default function TruncateText({ text }) {
return ( return (
<Tooltip title={text}> <Tooltip title={text}>
<EllipseText variant="body2">{text}</EllipseText> <Box height={34} overflow="hidden">
{/* todo add ellipsis */}
<Typography variant="body2" sx={{ wordBreak: 'break-word' }}>
{text}
</Typography>
</Box>
</Tooltip> </Tooltip>
); );
} }

View file

@ -6,12 +6,18 @@ export enum CollectionType {
folder = 'folder', folder = 'folder',
favorites = 'favorites', favorites = 'favorites',
album = 'album', album = 'album',
}
export enum CollectionSummaryType {
folder = 'folder',
favorites = 'favorites',
album = 'album',
archive = 'archive', archive = 'archive',
trash = 'trash', trash = 'trash',
all = 'all', all = 'all',
shared = 'shared', shared = 'shared',
archived = 'archived',
} }
export enum COLLECTION_SORT_BY { export enum COLLECTION_SORT_BY {
NAME, NAME,
CREATION_TIME_ASCENDING, CREATION_TIME_ASCENDING,
@ -24,34 +30,37 @@ export const COLLECTION_SHARE_DEFAULT_VALID_DURATION =
export const COLLECTION_SHARE_DEFAULT_DEVICE_LIMIT = 4; export const COLLECTION_SHARE_DEFAULT_DEVICE_LIMIT = 4;
export const COLLECTION_SORT_ORDER = new Map([ export const COLLECTION_SORT_ORDER = new Map([
[CollectionType.all, 0], [CollectionSummaryType.all, 0],
[CollectionType.favorites, 1], [CollectionSummaryType.favorites, 1],
[CollectionType.album, 2], [CollectionSummaryType.album, 2],
[CollectionType.folder, 2], [CollectionSummaryType.folder, 2],
[CollectionType.shared, 2], [CollectionSummaryType.shared, 2],
[CollectionType.archive, 3], [CollectionSummaryType.archived, 2],
[CollectionType.trash, 4], [CollectionSummaryType.archive, 3],
[CollectionSummaryType.trash, 4],
]); ]);
export const SYSTEM_COLLECTION_TYPES = new Set([ export const SYSTEM_COLLECTION_TYPES = new Set([
CollectionType.all, CollectionSummaryType.all,
CollectionType.archive, CollectionSummaryType.archive,
CollectionType.trash, CollectionSummaryType.trash,
]); ]);
export const UPLOAD_ALLOWED_COLLECTION_TYPES = new Set([ export const UPLOAD_NOT_ALLOWED_COLLECTION_TYPES = new Set([
CollectionType.album, CollectionSummaryType.all,
CollectionType.folder, CollectionSummaryType.archive,
CollectionType.favorites, CollectionSummaryType.shared,
CollectionSummaryType.trash,
]); ]);
export const OPTIONS_HAVING_COLLECTION_TYPES = new Set([ export const OPTIONS_NOT_HAVING_COLLECTION_TYPES = new Set([
CollectionType.folder, CollectionSummaryType.all,
CollectionType.album, CollectionSummaryType.archive,
CollectionType.trash, CollectionSummaryType.shared,
CollectionSummaryType.favorites,
]); ]);
export const HIDE_FROM_COLLECTION_BAR_TYPES = new Set([ export const HIDE_FROM_COLLECTION_BAR_TYPES = new Set([
CollectionType.trash, CollectionSummaryType.trash,
CollectionType.archive, CollectionSummaryType.archive,
]); ]);

View file

@ -32,6 +32,7 @@ import {
TRASH_SECTION, TRASH_SECTION,
COLLECTION_SORT_ORDER, COLLECTION_SORT_ORDER,
ALL_SECTION, ALL_SECTION,
CollectionSummaryType,
} from 'constants/collection'; } from 'constants/collection';
import { UpdateMagicMetadataRequest } from 'types/magicMetadata'; import { UpdateMagicMetadataRequest } from 'types/magicMetadata';
import { EncryptionResult } from 'types/upload'; import { EncryptionResult } from 'types/upload';
@ -786,8 +787,10 @@ export function getCollectionSummaries(
updationTime: collection.updationTime, updationTime: collection.updationTime,
type: type:
collection.owner.id !== user.id collection.owner.id !== user.id
? CollectionType.shared ? CollectionSummaryType.shared
: collection.type, : IsArchived(collection)
? CollectionSummaryType.archived
: CollectionSummaryType[collection.type],
}); });
} }
} }
@ -853,7 +856,7 @@ function getAllCollectionSummaries(
return { return {
id: ALL_SECTION, id: ALL_SECTION,
name: constants.ALL_SECTION_NAME, name: constants.ALL_SECTION_NAME,
type: CollectionType.all, type: CollectionSummaryType.all,
latestFile: collectionsLatestFile.get(ALL_SECTION), latestFile: collectionsLatestFile.get(ALL_SECTION),
fileCount: allSectionFileCount, fileCount: allSectionFileCount,
updationTime: collectionsLatestFile.get(ALL_SECTION)?.updationTime, updationTime: collectionsLatestFile.get(ALL_SECTION)?.updationTime,
@ -867,7 +870,7 @@ function getArchivedCollectionSummaries(
return { return {
id: ARCHIVE_SECTION, id: ARCHIVE_SECTION,
name: constants.ARCHIVE_SECTION_NAME, name: constants.ARCHIVE_SECTION_NAME,
type: CollectionType.archive, type: CollectionSummaryType.archive,
latestFile: collectionsLatestFile.get(ARCHIVE_SECTION), latestFile: collectionsLatestFile.get(ARCHIVE_SECTION),
fileCount: collectionFilesCount.get(ARCHIVE_SECTION) ?? 0, fileCount: collectionFilesCount.get(ARCHIVE_SECTION) ?? 0,
updationTime: collectionsLatestFile.get(ARCHIVE_SECTION)?.updationTime, updationTime: collectionsLatestFile.get(ARCHIVE_SECTION)?.updationTime,
@ -881,7 +884,7 @@ function getTrashedCollectionSummaries(
return { return {
id: TRASH_SECTION, id: TRASH_SECTION,
name: constants.TRASH, name: constants.TRASH,
type: CollectionType.trash, type: CollectionSummaryType.trash,
latestFile: collectionsLatestFile.get(TRASH_SECTION), latestFile: collectionsLatestFile.get(TRASH_SECTION),
fileCount: collectionFilesCount.get(TRASH_SECTION) ?? 0, fileCount: collectionFilesCount.get(TRASH_SECTION) ?? 0,
updationTime: collectionsLatestFile.get(TRASH_SECTION)?.updationTime, updationTime: collectionsLatestFile.get(TRASH_SECTION)?.updationTime,

View file

@ -1,6 +1,6 @@
import { User } from 'types/user'; import { User } from 'types/user';
import { EnteFile } from 'types/file'; import { EnteFile } from 'types/file';
import { CollectionType } from 'constants/collection'; import { CollectionSummaryType, CollectionType } from 'constants/collection';
import { MagicMetadataCore, VISIBILITY_STATE } from 'types/magicMetadata'; import { MagicMetadataCore, VISIBILITY_STATE } from 'types/magicMetadata';
export interface Collection { export interface Collection {
@ -91,7 +91,7 @@ export interface CollectionMagicMetadata
export interface CollectionSummary { export interface CollectionSummary {
id: number; id: number;
name: string; name: string;
type: CollectionType; type: CollectionSummaryType;
latestFile: EnteFile; latestFile: EnteFile;
fileCount: number; fileCount: number;
updationTime: number; updationTime: number;
@ -99,10 +99,3 @@ export interface CollectionSummary {
export type CollectionSummaries = Map<number, CollectionSummary>; export type CollectionSummaries = Map<number, CollectionSummary>;
export type CollectionFilesCount = Map<number, number>; export type CollectionFilesCount = Map<number, number>;
export interface CollectionInfo {
id: number;
name: string;
fileCount: number;
type: CollectionType;
}

View file

@ -20,11 +20,12 @@ import {
CollectionSummaries, CollectionSummaries,
} from 'types/collection'; } from 'types/collection';
import { import {
CollectionSummaryType,
CollectionType, CollectionType,
HIDE_FROM_COLLECTION_BAR_TYPES, HIDE_FROM_COLLECTION_BAR_TYPES,
OPTIONS_HAVING_COLLECTION_TYPES, OPTIONS_NOT_HAVING_COLLECTION_TYPES,
SYSTEM_COLLECTION_TYPES, SYSTEM_COLLECTION_TYPES,
UPLOAD_ALLOWED_COLLECTION_TYPES, UPLOAD_NOT_ALLOWED_COLLECTION_TYPES,
} from 'constants/collection'; } from 'constants/collection';
import { getAlbumSiteHost } from 'constants/pages'; import { getAlbumSiteHost } from 'constants/pages';
import { getUnixTimeInMicroSecondsWithDelta } from 'utils/time'; import { getUnixTimeInMicroSecondsWithDelta } from 'utils/time';
@ -208,18 +209,18 @@ export const hasNonEmptyCollections = (
return collectionSummaries?.size <= 3; return collectionSummaries?.size <= 3;
}; };
export const isUploadAllowedCollection = (type: CollectionType) => { export const isUploadAllowedCollection = (type: CollectionSummaryType) => {
return UPLOAD_ALLOWED_COLLECTION_TYPES.has(type); return !UPLOAD_NOT_ALLOWED_COLLECTION_TYPES.has(type);
}; };
export const isSystemCollection = (type: CollectionType) => { export const isSystemCollection = (type: CollectionSummaryType) => {
return SYSTEM_COLLECTION_TYPES.has(type); return SYSTEM_COLLECTION_TYPES.has(type);
}; };
export const isOptionsHavingCollection = (type: CollectionType) => { export const shouldShowOptions = (type: CollectionSummaryType) => {
return OPTIONS_HAVING_COLLECTION_TYPES.has(type); return !OPTIONS_NOT_HAVING_COLLECTION_TYPES.has(type);
}; };
export const shouldBeShownOnCollectionBar = (type: CollectionType) => { export const shouldBeShownOnCollectionBar = (type: CollectionSummaryType) => {
return !HIDE_FROM_COLLECTION_BAR_TYPES.has(type); return !HIDE_FROM_COLLECTION_BAR_TYPES.has(type);
}; };