Merge pull request #191 from ente-io/master

Mid Oct Release
This commit is contained in:
Abhinav-grd 2021-10-22 14:42:23 +05:30 committed by GitHub
commit 44a37ad387
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 123 additions and 23 deletions

View file

@ -185,6 +185,14 @@ const PhotoFrame = ({
timeTaken: (Date.now() - startTime) / 1000,
});
}
if (search.fileIndex || search.fileIndex === 0) {
const filteredDataIdx = filteredData.findIndex(
(data) => data.dataIndex === search.fileIndex
);
if (filteredDataIdx || filteredDataIdx === 0) {
onThumbnailClick(filteredDataIdx)();
}
}
}, [search]);
useEffect(() => {

View file

@ -10,6 +10,7 @@ import {
getYearSuggestion,
parseHumanDate,
searchCollection,
searchFiles,
searchLocation,
} from 'services/searchService';
import { getFormattedDate } from 'utils/search';
@ -20,6 +21,9 @@ import SearchIcon from './icons/SearchIcon';
import CrossIcon from './icons/CrossIcon';
import { Collection } from 'services/collectionService';
import CollectionIcon from './icons/CollectionIcon';
import { File, FILE_TYPE } from 'services/fileService';
import ImageIcon from './icons/ImageIcon';
import VideoIcon from './icons/VideoIcon';
const Wrapper = styled.div<{ isDisabled: boolean; isOpen: boolean }>`
position: fixed;
@ -74,6 +78,8 @@ export enum SuggestionType {
DATE,
LOCATION,
COLLECTION,
IMAGE,
VIDEO,
}
export interface DateValue {
date?: number;
@ -94,6 +100,7 @@ interface Props {
searchStats: SearchStats;
collections: Collection[];
setActiveCollection: (id: number) => void;
files: File[];
}
export default function SearchBar(props: Props) {
const [value, setValue] = useState<Suggestion>(null);
@ -112,14 +119,14 @@ export default function SearchBar(props: Props) {
if (!searchPhrase?.length) {
return [];
}
const option = [
const options = [
...getHolidaySuggestion(searchPhrase),
...getYearSuggestion(searchPhrase),
];
const searchedDates = parseHumanDate(searchPhrase);
option.push(
options.push(
...searchedDates.map((searchedDate) => ({
type: SuggestionType.DATE,
value: searchedDate,
@ -131,7 +138,7 @@ export default function SearchBar(props: Props) {
searchPhrase,
props.collections
);
option.push(
options.push(
...collectionResults.map(
(searchResult) =>
({
@ -141,8 +148,20 @@ export default function SearchBar(props: Props) {
} as Suggestion)
)
);
const fileResults = searchFiles(searchPhrase, props.files);
options.push(
...fileResults.map((file) => ({
type:
file.type === FILE_TYPE.IMAGE
? SuggestionType.IMAGE
: SuggestionType.VIDEO,
value: file.index,
label: file.title,
}))
);
const locationResults = await searchLocation(searchPhrase);
option.push(
options.push(
...locationResults.map(
(searchResult) =>
({
@ -152,7 +171,7 @@ export default function SearchBar(props: Props) {
} as Suggestion)
)
);
return option;
return options;
};
const getOptions = debounce(getAutoCompleteSuggestions, 250);
@ -161,7 +180,6 @@ export default function SearchBar(props: Props) {
if (!selectedOption) {
return;
}
switch (selectedOption.type) {
case SuggestionType.DATE:
props.setSearch({
@ -179,6 +197,11 @@ export default function SearchBar(props: Props) {
props.setActiveCollection(selectedOption.value as number);
setValue(null);
break;
case SuggestionType.IMAGE:
case SuggestionType.VIDEO:
props.setSearch({ fileIndex: selectedOption.value as number });
setValue(null);
break;
}
};
const resetSearch = () => {
@ -205,6 +228,10 @@ export default function SearchBar(props: Props) {
return <LocationIcon />;
case SuggestionType.COLLECTION:
return <CollectionIcon />;
case SuggestionType.IMAGE:
return <ImageIcon />;
case SuggestionType.VIDEO:
return <VideoIcon />;
default:
return <SearchIcon />;
}

View file

@ -0,0 +1,21 @@
import React from 'react';
export default function ImageIcon(props) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height={props.height}
viewBox={props.viewBox}
width={props.width}
fill="currentColor">
<path d="M0 0h24v24H0V0z" fill="none" />
<path d="M19 5v14H5V5h14m0-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-4.86 8.86l-3 3.87L9 13.14 6 17h12l-3.86-5.14z" />
</svg>
);
}
ImageIcon.defaultProps = {
height: 24,
width: 24,
viewBox: '0 0 24 24',
};

View file

@ -0,0 +1,20 @@
import React from 'react';
export default function VideoIcon(props) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
height={props.height}
viewBox={props.viewBox}
width={props.width}
fill="currentColor">
<path d="M4 6.47L5.76 10H20v8H4V6.47M22 4h-4l2 4h-3l-2-4h-2l2 4h-3l-2-4H8l2 4H7L5 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4z" />
</svg>
);
}
VideoIcon.defaultProps = {
height: 24,
width: 24,
viewBox: '0 0 24 24',
};

View file

@ -106,6 +106,7 @@ export type setSearchStats = React.Dispatch<React.SetStateAction<SearchStats>>;
export type Search = {
date?: DateValue;
location?: Bbox;
fileIndex?: number;
};
export interface SearchStats {
resultCount: number;
@ -159,6 +160,7 @@ export default function Gallery() {
const [search, setSearch] = useState<Search>({
date: null,
location: null,
fileIndex: null,
});
const [uploadInProgress, setUploadInProgress] = useState(false);
const {
@ -184,11 +186,6 @@ export default function Gallery() {
useState<Map<number, number>>();
const [activeCollection, setActiveCollection] = useState<number>(undefined);
const [isSharedCollectionActive, setIsSharedCollectionActive] =
useState(false);
const [isFavCollectionActive, setIsFavCollectionActive] = useState(false);
useEffect(() => {
const key = getKey(SESSION_KEYS.ENCRYPTION_KEY);
if (!key) {
@ -246,14 +243,6 @@ export default function Gallery() {
}
const href = `/gallery${collectionURL}`;
router.push(href, undefined, { shallow: true });
setIsSharedCollectionActive(
isSharedCollection(activeCollection, collections)
);
setIsFavCollectionActive(
isFavoriteCollection(activeCollection, collections)
);
}, [activeCollection]);
const syncWithRemote = async (force = false, silent = false) => {
@ -544,6 +533,7 @@ export default function Gallery() {
loadingBar={loadingBar}
isFirstFetch={isFirstFetch}
collections={collections}
files={files}
setActiveCollection={setActiveCollection}
setSearch={updateSearch}
searchStats={searchStats}
@ -624,7 +614,10 @@ export default function Gallery() {
deleted={deleted}
setDialogMessage={setDialogMessage}
activeCollection={activeCollection}
isSharedCollection={isSharedCollectionActive}
isSharedCollection={isSharedCollection(
activeCollection,
collections
)}
/>
{selected.count > 0 &&
selected.collectionID === activeCollection && (
@ -652,7 +645,10 @@ export default function Gallery() {
count={selected.count}
clearSelection={clearSelection}
activeCollection={activeCollection}
isFavoriteCollection={isFavCollectionActive}
isFavoriteCollection={isFavoriteCollection(
activeCollection,
collections
)}
/>
)}
</FullScreenDropZone>

View file

@ -23,7 +23,6 @@ export enum CollectionType {
}
const COLLECTION_UPDATION_TIME = 'collection-updation-time';
const FAV_COLLECTION = 'fav-collection';
const COLLECTIONS = 'collections';
export interface Collection {
@ -340,7 +339,11 @@ export const addToFavorites = async (file: File) => {
'Favorites',
CollectionType.favorites
);
await localForage.setItem(FAV_COLLECTION, favCollection);
const localCollections = await getLocalCollections();
await localForage.setItem(COLLECTIONS, [
...localCollections,
favCollection,
]);
}
await addToCollection(favCollection, [file]);
} catch (e) {

View file

@ -4,6 +4,9 @@ import { getToken } from 'utils/common/key';
import { DateValue, Suggestion, SuggestionType } from 'components/SearchBar';
import HTTPService from './HTTPService';
import { Collection } from './collectionService';
import { File } from './fileService';
import { User } from './userService';
import { getData, LS_KEYS } from 'utils/storage/localStorage';
const ENDPOINT = getEndpoint();
const DIGITS = new Set(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']);
@ -110,3 +113,25 @@ export function searchCollection(
collection.name.toLowerCase().includes(searchPhrase)
);
}
export function searchFiles(searchPhrase: string, files: File[]) {
const user: User = getData(LS_KEYS.USER) ?? {};
const idSet = new Set();
return files
.map((file, idx) => ({
title: file.metadata.title,
index: idx,
type: file.metadata.fileType,
ownerID: file.ownerID,
id: file.id,
}))
.filter((file) => {
if (file.ownerID === user.id && !idSet.has(file.id)) {
idSet.add(file.id);
return true;
}
return false;
})
.filter(({ title }) => title.toLowerCase().includes(searchPhrase))
.slice(0, 4);
}