Merge pull request #11 from ente-io/collection-delete
handling collection deleted from remote
This commit is contained in:
commit
5b17b2a322
|
@ -51,7 +51,6 @@ function PhotoSwipe(props: Iprops) {
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
function updateFavButton() {
|
function updateFavButton() {
|
||||||
console.log(this.currItem.id, props.favItemIds)
|
|
||||||
setIsFav(isInFav(this?.currItem));
|
setIsFav(isInFav(this?.currItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,14 +112,12 @@ function PhotoSwipe(props: Iprops) {
|
||||||
if (!isInFav(file)) {
|
if (!isInFav(file)) {
|
||||||
favItemIds.add(file.id);
|
favItemIds.add(file.id);
|
||||||
await addToFavorites(file);
|
await addToFavorites(file);
|
||||||
console.log("added to Favorites");
|
|
||||||
setIsFav(true);
|
setIsFav(true);
|
||||||
setFavItemIds(favItemIds);
|
setFavItemIds(favItemIds);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
favItemIds.delete(file.id);
|
favItemIds.delete(file.id);
|
||||||
await removeFromFavorites(file)
|
await removeFromFavorites(file)
|
||||||
console.log("removed from Favorites");
|
|
||||||
setIsFav(false);
|
setIsFav(false);
|
||||||
setFavItemIds(favItemIds);
|
setFavItemIds(favItemIds);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ function CollectionDropZone({
|
||||||
closeModal,
|
closeModal,
|
||||||
showModal,
|
showModal,
|
||||||
refetchData,
|
refetchData,
|
||||||
collectionLatestFile,
|
collectionAndItsLatestFile,
|
||||||
setProgressView,
|
setProgressView,
|
||||||
progressBarProps
|
progressBarProps
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ function CollectionDropZone({
|
||||||
progressBarProps.setPercentComplete(0);
|
progressBarProps.setPercentComplete(0);
|
||||||
setProgressView(true);
|
setProgressView(true);
|
||||||
|
|
||||||
await UploadService.uploadFiles(acceptedFiles, collectionLatestFile, token, progressBarProps);
|
await UploadService.uploadFiles(acceptedFiles, collectionAndItsLatestFile, token, progressBarProps);
|
||||||
refetchData();
|
refetchData();
|
||||||
setProgressView(false);
|
setProgressView(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,17 +10,16 @@ function CollectionSelector(props) {
|
||||||
uploadModalView,
|
uploadModalView,
|
||||||
closeUploadModal,
|
closeUploadModal,
|
||||||
showUploadModal,
|
showUploadModal,
|
||||||
collectionLatestFile,
|
collectionAndItsLatestFile,
|
||||||
...rest
|
...rest
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
|
const CollectionIcons = collectionAndItsLatestFile?.map((item) => (
|
||||||
const CollectionIcons = collectionLatestFile?.map((item) => (
|
|
||||||
<CollectionDropZone key={item.collection.id}
|
<CollectionDropZone key={item.collection.id}
|
||||||
{...rest}
|
{...rest}
|
||||||
closeModal={closeUploadModal}
|
closeModal={closeUploadModal}
|
||||||
showModal={showUploadModal}
|
showModal={showUploadModal}
|
||||||
collectionLatestFile={item}
|
collectionAndItsLatestFile={item}
|
||||||
>
|
>
|
||||||
<Card>
|
<Card>
|
||||||
<PreviewCard data={item.file} updateUrl={() => { }} forcedEnable />
|
<PreviewCard data={item.file} updateUrl={() => { }} forcedEnable />
|
||||||
|
|
|
@ -5,7 +5,7 @@ import styled from 'styled-components';
|
||||||
interface CollectionProps {
|
interface CollectionProps {
|
||||||
collections: collection[];
|
collections: collection[];
|
||||||
selected?: string;
|
selected?: string;
|
||||||
selectCollection: (id?: string) => void;
|
selectCollection: (id?: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
|
@ -51,7 +51,7 @@ const Chip = styled.button<{ active: boolean }>`
|
||||||
|
|
||||||
export default function Collections(props: CollectionProps) {
|
export default function Collections(props: CollectionProps) {
|
||||||
const { selected, collections, selectCollection } = props;
|
const { selected, collections, selectCollection } = props;
|
||||||
const clickHandler = (id?: string) => () => selectCollection(id);
|
const clickHandler = (id?: number) => () => selectCollection(id);
|
||||||
|
|
||||||
return <Container>
|
return <Container>
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
||||||
import { Button, Form, Modal } from 'react-bootstrap';
|
import { Button, Form, Modal } from 'react-bootstrap';
|
||||||
import { createAlbum } from 'services/collectionService';
|
import { createAlbum } from 'services/collectionService';
|
||||||
import UploadService from 'services/uploadService';
|
import UploadService from 'services/uploadService';
|
||||||
import { collectionLatestFile } from 'services/collectionService'
|
import { CollectionAndItsLatestFile } from 'services/collectionService'
|
||||||
import { getToken } from 'utils/common/key';
|
import { getToken } from 'utils/common/key';
|
||||||
|
|
||||||
export default function CreateCollection(props) {
|
export default function CreateCollection(props) {
|
||||||
|
@ -35,12 +35,12 @@ export default function CreateCollection(props) {
|
||||||
|
|
||||||
const collection = await createAlbum(albumName);
|
const collection = await createAlbum(albumName);
|
||||||
|
|
||||||
const collectionLatestFile: collectionLatestFile = { collection, file: null }
|
const collectionAndItsLatestFile: CollectionAndItsLatestFile = { collection, file: null }
|
||||||
|
|
||||||
progressBarProps.setPercentComplete(0);
|
progressBarProps.setPercentComplete(0);
|
||||||
setProgressView(true);
|
setProgressView(true);
|
||||||
|
|
||||||
await UploadService.uploadFiles(acceptedFiles, collectionLatestFile, token, progressBarProps);
|
await UploadService.uploadFiles(acceptedFiles, collectionAndItsLatestFile, token, progressBarProps);
|
||||||
refetchData();
|
refetchData();
|
||||||
setProgressView(false);
|
setProgressView(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
file,
|
file,
|
||||||
getFile,
|
getFile,
|
||||||
getPreview,
|
getPreview,
|
||||||
fetchData,
|
syncData,
|
||||||
localFiles,
|
localFiles,
|
||||||
} from 'services/fileService';
|
} from 'services/fileService';
|
||||||
import { getData, LS_KEYS } from 'utils/storage/localStorage';
|
import { getData, LS_KEYS } from 'utils/storage/localStorage';
|
||||||
|
@ -22,9 +22,9 @@ import Collections from './components/Collections';
|
||||||
import Upload from './components/Upload';
|
import Upload from './components/Upload';
|
||||||
import {
|
import {
|
||||||
collection,
|
collection,
|
||||||
fetchUpdatedCollections,
|
syncCollections,
|
||||||
collectionLatestFile,
|
CollectionAndItsLatestFile,
|
||||||
getCollectionLatestFile,
|
getCollectionAndItsLatestFile,
|
||||||
getFavItemIds,
|
getFavItemIds,
|
||||||
getLocalCollections,
|
getLocalCollections,
|
||||||
} from 'services/collectionService';
|
} from 'services/collectionService';
|
||||||
|
@ -108,9 +108,10 @@ export default function Gallery(props) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [collections, setCollections] = useState<collection[]>([]);
|
const [collections, setCollections] = useState<collection[]>([]);
|
||||||
const [collectionLatestFile, setCollectionLatestFile] = useState<
|
const [
|
||||||
collectionLatestFile[]
|
collectionAndItsLatestFile,
|
||||||
>([]);
|
setCollectionAndItsLatestFile,
|
||||||
|
] = useState<CollectionAndItsLatestFile[]>([]);
|
||||||
const [data, setData] = useState<file[]>();
|
const [data, setData] = useState<file[]>();
|
||||||
const [favItemIds, setFavItemIds] = useState<Set<number>>();
|
const [favItemIds, setFavItemIds] = useState<Set<number>>();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
@ -132,8 +133,16 @@ export default function Gallery(props) {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const data = await localFiles();
|
const data = await localFiles();
|
||||||
const collections = await getLocalCollections();
|
const collections = await getLocalCollections();
|
||||||
|
const collectionAndItsLatestFile = await getCollectionAndItsLatestFile(
|
||||||
|
collections,
|
||||||
|
data
|
||||||
|
);
|
||||||
setData(data);
|
setData(data);
|
||||||
setCollections(collections);
|
setCollections(collections);
|
||||||
|
setCollectionAndItsLatestFile(collectionAndItsLatestFile);
|
||||||
|
const favItemIds = await getFavItemIds(data);
|
||||||
|
setFavItemIds(favItemIds);
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setProgress(80);
|
setProgress(80);
|
||||||
await syncWithRemote();
|
await syncWithRemote();
|
||||||
|
@ -146,22 +155,18 @@ export default function Gallery(props) {
|
||||||
const syncWithRemote = async () => {
|
const syncWithRemote = async () => {
|
||||||
const token = getToken();
|
const token = getToken();
|
||||||
const encryptionKey = await getActualKey();
|
const encryptionKey = await getActualKey();
|
||||||
const updatedCollections = await fetchUpdatedCollections(
|
const collections = await syncCollections(token, encryptionKey);
|
||||||
token,
|
const { data, isUpdated } = await syncData(token, collections);
|
||||||
encryptionKey
|
const collectionAndItsLatestFile = await getCollectionAndItsLatestFile(
|
||||||
);
|
|
||||||
const data = await fetchData(token, updatedCollections);
|
|
||||||
const collections = await getLocalCollections();
|
|
||||||
const collectionLatestFile = await getCollectionLatestFile(
|
|
||||||
collections,
|
collections,
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
const favItemIds = await getFavItemIds(data);
|
const favItemIds = await getFavItemIds(data);
|
||||||
if (updatedCollections.length > 0) {
|
setCollections(collections);
|
||||||
setCollections(collections);
|
if (isUpdated) {
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
setCollectionLatestFile(collectionLatestFile);
|
setCollectionAndItsLatestFile(collectionAndItsLatestFile);
|
||||||
setFavItemIds(favItemIds);
|
setFavItemIds(favItemIds);
|
||||||
setSinceTime(new Date().getTime());
|
setSinceTime(new Date().getTime());
|
||||||
props.setUploadButtonView(true);
|
props.setUploadButtonView(true);
|
||||||
|
@ -295,7 +300,7 @@ export default function Gallery(props) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectCollection = (id?: string) => {
|
const selectCollection = (id?: number) => {
|
||||||
const href = `/gallery?collection=${id || ''}`;
|
const href = `/gallery?collection=${id || ''}`;
|
||||||
router.push(href, undefined, { shallow: true });
|
router.push(href, undefined, { shallow: true });
|
||||||
};
|
};
|
||||||
|
@ -344,7 +349,7 @@ export default function Gallery(props) {
|
||||||
uploadModalView={props.uploadModalView}
|
uploadModalView={props.uploadModalView}
|
||||||
closeUploadModal={props.closeUploadModal}
|
closeUploadModal={props.closeUploadModal}
|
||||||
showUploadModal={props.showUploadModal}
|
showUploadModal={props.showUploadModal}
|
||||||
collectionLatestFile={collectionLatestFile}
|
collectionAndItsLatestFile={collectionAndItsLatestFile}
|
||||||
refetchData={syncWithRemote}
|
refetchData={syncWithRemote}
|
||||||
/>
|
/>
|
||||||
{filteredData.length ? (
|
{filteredData.length ? (
|
||||||
|
|
|
@ -1,35 +1,37 @@
|
||||||
import { getEndpoint } from "utils/common/apiUtil";
|
import { getEndpoint } from 'utils/common/apiUtil';
|
||||||
import { getData, LS_KEYS } from "utils/storage/localStorage";
|
import { getData, LS_KEYS } from 'utils/storage/localStorage';
|
||||||
import { file, user, getFiles } from "./fileService";
|
import { file, user, getFiles } from './fileService';
|
||||||
import localForage from 'localforage';
|
import localForage from 'localforage';
|
||||||
|
|
||||||
import HTTPService from "./HTTPService";
|
import HTTPService from './HTTPService';
|
||||||
import * as Comlink from 'comlink';
|
import * as Comlink from 'comlink';
|
||||||
import { keyEncryptionResult } from "./uploadService";
|
import { keyEncryptionResult } from './uploadService';
|
||||||
import { getActualKey, getToken } from "utils/common/key";
|
import { getActualKey, getToken } from 'utils/common/key';
|
||||||
|
|
||||||
|
|
||||||
const CryptoWorker: any =
|
const CryptoWorker: any =
|
||||||
typeof window !== 'undefined' &&
|
typeof window !== 'undefined' &&
|
||||||
Comlink.wrap(new Worker('worker/crypto.worker.js', { type: 'module' }));
|
Comlink.wrap(new Worker('worker/crypto.worker.js', { type: 'module' }));
|
||||||
const ENDPOINT = getEndpoint();
|
const ENDPOINT = getEndpoint();
|
||||||
|
|
||||||
|
|
||||||
enum CollectionType {
|
enum CollectionType {
|
||||||
folder = "folder",
|
folder = 'folder',
|
||||||
favorites = "favorites",
|
favorites = 'favorites',
|
||||||
album = "album",
|
album = 'album',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const COLLECTION_UPDATION_TIME = 'collection-updation-time';
|
||||||
|
const FAV_COLLECTION = 'fav-collection';
|
||||||
|
const COLLECTIONS = 'collections';
|
||||||
|
|
||||||
export interface collection {
|
export interface collection {
|
||||||
id: string;
|
id: number;
|
||||||
owner: user;
|
owner: user;
|
||||||
key?: string;
|
key?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
encryptedName?: string;
|
encryptedName?: string;
|
||||||
nameDecryptionNonce?: string;
|
nameDecryptionNonce?: string;
|
||||||
type: string;
|
type: string;
|
||||||
attributes: collectionAttributes
|
attributes: collectionAttributes;
|
||||||
sharees: user[];
|
sharees: user[];
|
||||||
updationTime: number;
|
updationTime: number;
|
||||||
encryptedKey: string;
|
encryptedKey: string;
|
||||||
|
@ -39,16 +41,18 @@ export interface collection {
|
||||||
|
|
||||||
interface collectionAttributes {
|
interface collectionAttributes {
|
||||||
encryptedPath?: string;
|
encryptedPath?: string;
|
||||||
pathDecryptionNonce?: string
|
pathDecryptionNonce?: string;
|
||||||
};
|
}
|
||||||
|
|
||||||
export interface collectionLatestFile {
|
export interface CollectionAndItsLatestFile {
|
||||||
collection: collection
|
collection: collection;
|
||||||
file: file;
|
file: file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getCollectionSecrets = async (
|
||||||
const getCollectionSecrets = async (collection: collection, masterKey: string) => {
|
collection: collection,
|
||||||
|
masterKey: string
|
||||||
|
) => {
|
||||||
const worker = await new CryptoWorker();
|
const worker = await new CryptoWorker();
|
||||||
const userID = getData(LS_KEYS.USER).id;
|
const userID = getData(LS_KEYS.USER).id;
|
||||||
let decryptedKey: string;
|
let decryptedKey: string;
|
||||||
|
@ -58,7 +62,6 @@ const getCollectionSecrets = async (collection: collection, masterKey: string) =
|
||||||
collection.keyDecryptionNonce,
|
collection.keyDecryptionNonce,
|
||||||
masterKey
|
masterKey
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const keyAttributes = getData(LS_KEYS.KEY_ATTRIBUTES);
|
const keyAttributes = getData(LS_KEYS.KEY_ATTRIBUTES);
|
||||||
const secretKey = await worker.decryptB64(
|
const secretKey = await worker.decryptB64(
|
||||||
|
@ -72,10 +75,13 @@ const getCollectionSecrets = async (collection: collection, masterKey: string) =
|
||||||
secretKey
|
secretKey
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
collection.name = collection.name || await worker.decryptString(
|
collection.name =
|
||||||
collection.encryptedName,
|
collection.name ||
|
||||||
collection.nameDecryptionNonce,
|
(await worker.decryptString(
|
||||||
decryptedKey);
|
collection.encryptedName,
|
||||||
|
collection.nameDecryptionNonce,
|
||||||
|
decryptedKey
|
||||||
|
));
|
||||||
return {
|
return {
|
||||||
...collection,
|
...collection,
|
||||||
key: decryptedKey,
|
key: decryptedKey,
|
||||||
|
@ -88,85 +94,131 @@ const getCollections = async (
|
||||||
key: string
|
key: string
|
||||||
): Promise<collection[]> => {
|
): Promise<collection[]> => {
|
||||||
try {
|
try {
|
||||||
const resp = await HTTPService.get(`${ENDPOINT}/collections`, {
|
const resp = await HTTPService.get(
|
||||||
sinceTime: sinceTime,
|
`${ENDPOINT}/collections`,
|
||||||
}, { 'X-Auth-Token': token, });
|
{
|
||||||
|
sinceTime: sinceTime,
|
||||||
|
},
|
||||||
|
{ 'X-Auth-Token': token }
|
||||||
|
);
|
||||||
const promises: Promise<collection>[] = resp.data.collections.map(
|
const promises: Promise<collection>[] = resp.data.collections.map(
|
||||||
(collection: collection) => getCollectionSecrets(collection, key)
|
(collection: collection) => getCollectionSecrets(collection, key)
|
||||||
);
|
);
|
||||||
return await Promise.all(promises);
|
return await Promise.all(promises);
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
console.log('getCollections failed- ' + e);
|
||||||
console.log("getCollections failed- " + e);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLocalCollections = async (): Promise<collection[]> => {
|
export const getLocalCollections = async (): Promise<collection[]> => {
|
||||||
const collections = await localForage.getItem('collections') as collection[] ?? [];
|
const collections: collection[] =
|
||||||
|
(await localForage.getItem(COLLECTIONS)) ?? [];
|
||||||
return collections;
|
return collections;
|
||||||
}
|
};
|
||||||
export const fetchUpdatedCollections = async (token: string, key: string) => {
|
|
||||||
const collectionUpdateTime = await localForage.getItem('collection-update-time') as string;
|
export const syncCollections = async (token: string, key: string) => {
|
||||||
const updatedCollections = await getCollections(token, collectionUpdateTime ?? '0', key) || [];
|
|
||||||
const favCollection = await localForage.getItem('fav-collection') as collection[] ?? updatedCollections.filter(collection => collection.type === CollectionType.favorites);
|
|
||||||
const localCollections = await getLocalCollections();
|
const localCollections = await getLocalCollections();
|
||||||
const allCollectionsInstances = [...localCollections, ...updatedCollections];
|
const lastCollectionUpdationTime =
|
||||||
var latestCollectionsInstances = new Map<string, collection>();
|
(await localForage.getItem<string>(COLLECTION_UPDATION_TIME)) ?? '0';
|
||||||
|
const updatedCollections =
|
||||||
|
(await getCollections(token, lastCollectionUpdationTime, key)) || [];
|
||||||
|
|
||||||
|
if (updatedCollections.length == 0) {
|
||||||
|
return localCollections;
|
||||||
|
}
|
||||||
|
setLocalFavoriteCollection(updatedCollections);
|
||||||
|
const allCollectionsInstances = [
|
||||||
|
...localCollections,
|
||||||
|
...updatedCollections,
|
||||||
|
];
|
||||||
|
var latestCollectionsInstances = new Map<number, collection>();
|
||||||
allCollectionsInstances.forEach((collection) => {
|
allCollectionsInstances.forEach((collection) => {
|
||||||
if (!latestCollectionsInstances.has(collection.id) || latestCollectionsInstances.get(collection.id).updationTime < collection.updationTime) {
|
if (
|
||||||
|
!latestCollectionsInstances.has(collection.id) ||
|
||||||
|
latestCollectionsInstances.get(collection.id).updationTime <
|
||||||
|
collection.updationTime
|
||||||
|
) {
|
||||||
latestCollectionsInstances.set(collection.id, collection);
|
latestCollectionsInstances.set(collection.id, collection);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let collections = [];
|
|
||||||
|
let collections = [],
|
||||||
|
updationTime = await localForage.getItem<number>(
|
||||||
|
COLLECTION_UPDATION_TIME
|
||||||
|
);
|
||||||
for (const [_, collection] of latestCollectionsInstances) {
|
for (const [_, collection] of latestCollectionsInstances) {
|
||||||
collections.push(collection);
|
if (!collection.isDeleted) {
|
||||||
|
collections.push(collection);
|
||||||
|
updationTime = Math.max(updationTime, collection.updationTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
await localForage.setItem('fav-collection', favCollection);
|
await localForage.setItem(COLLECTION_UPDATION_TIME, updationTime);
|
||||||
await localForage.setItem('collections', collections);
|
await localForage.setItem(COLLECTIONS, collections);
|
||||||
return updatedCollections;
|
return collections;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCollectionLatestFile = (
|
export const getCollectionAndItsLatestFile = (
|
||||||
collections: collection[],
|
collections: collection[],
|
||||||
files: file[]
|
files: file[]
|
||||||
): collectionLatestFile[] => {
|
): CollectionAndItsLatestFile[] => {
|
||||||
const latestFile = new Map<number, file>();
|
const latestFile = new Map<number, file>();
|
||||||
const collectionMap = new Map<number, collection>();
|
const collectionMap = new Map<number, collection>();
|
||||||
|
|
||||||
collections.forEach(collection => collectionMap.set(Number(collection.id), collection));
|
collections.forEach((collection) =>
|
||||||
files.forEach(file => {
|
collectionMap.set(collection.id, collection)
|
||||||
|
);
|
||||||
|
files.forEach((file) => {
|
||||||
if (!latestFile.has(file.collectionID)) {
|
if (!latestFile.has(file.collectionID)) {
|
||||||
latestFile.set(file.collectionID, file)
|
latestFile.set(file.collectionID, file);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let allCollectionLatestFile: collectionLatestFile[] = [];
|
let allCollectionAndItsLatestFile: CollectionAndItsLatestFile[] = [];
|
||||||
for (const [collectionID, file] of latestFile) {
|
for (const [collectionID, file] of latestFile) {
|
||||||
allCollectionLatestFile.push({ collection: collectionMap.get(collectionID), file });
|
allCollectionAndItsLatestFile.push({
|
||||||
|
collection: collectionMap.get(collectionID),
|
||||||
|
file,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return allCollectionLatestFile;
|
return allCollectionAndItsLatestFile;
|
||||||
}
|
};
|
||||||
|
|
||||||
export const getFavItemIds = async (files: file[]): Promise<Set<number>> => {
|
export const getFavItemIds = async (files: file[]): Promise<Set<number>> => {
|
||||||
|
let favCollection = await localForage.getItem<collection>(FAV_COLLECTION);
|
||||||
|
if (!favCollection) return new Set();
|
||||||
|
|
||||||
let favCollection: collection = (await localForage.getItem<collection>('fav-collection'))[0];
|
return new Set(
|
||||||
if (!favCollection)
|
files
|
||||||
return new Set();
|
.filter((file) => file.collectionID === favCollection.id)
|
||||||
|
.map((file): number => file.id)
|
||||||
return new Set(files.filter(file => file.collectionID === Number(favCollection.id)).map((file): number => file.id));
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export const createAlbum = async (albumName: string) => {
|
export const createAlbum = async (albumName: string) => {
|
||||||
return AddCollection(albumName, CollectionType.album);
|
return AddCollection(albumName, CollectionType.album);
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export const AddCollection = async (
|
||||||
export const AddCollection = async (collectionName: string, type: CollectionType) => {
|
collectionName: string,
|
||||||
|
type: CollectionType
|
||||||
|
) => {
|
||||||
const worker = await new CryptoWorker();
|
const worker = await new CryptoWorker();
|
||||||
const encryptionKey = await getActualKey();
|
const encryptionKey = await getActualKey();
|
||||||
const token = getToken();
|
const token = getToken();
|
||||||
const collectionKey: string = await worker.generateMasterKey();
|
const collectionKey: string = await worker.generateMasterKey();
|
||||||
const { encryptedData: encryptedKey, nonce: keyDecryptionNonce }: keyEncryptionResult = await worker.encryptToB64(collectionKey, encryptionKey);
|
const {
|
||||||
const { encryptedData: encryptedName, nonce: nameDecryptionNonce }: keyEncryptionResult = await worker.encryptToB64(collectionName, collectionKey);
|
encryptedData: encryptedKey,
|
||||||
|
nonce: keyDecryptionNonce,
|
||||||
|
}: keyEncryptionResult = await worker.encryptToB64(
|
||||||
|
collectionKey,
|
||||||
|
encryptionKey
|
||||||
|
);
|
||||||
|
const {
|
||||||
|
encryptedData: encryptedName,
|
||||||
|
nonce: nameDecryptionNonce,
|
||||||
|
}: keyEncryptionResult = await worker.encryptToB64(
|
||||||
|
collectionName,
|
||||||
|
collectionKey
|
||||||
|
);
|
||||||
const newCollection: collection = {
|
const newCollection: collection = {
|
||||||
id: null,
|
id: null,
|
||||||
owner: null,
|
owner: null,
|
||||||
|
@ -178,76 +230,126 @@ export const AddCollection = async (collectionName: string, type: CollectionType
|
||||||
attributes: {},
|
attributes: {},
|
||||||
sharees: null,
|
sharees: null,
|
||||||
updationTime: null,
|
updationTime: null,
|
||||||
isDeleted: false
|
isDeleted: false,
|
||||||
};
|
};
|
||||||
let createdCollection: collection = await createCollection(newCollection, token);
|
let createdCollection: collection = await createCollection(
|
||||||
createdCollection = await getCollectionSecrets(createdCollection, encryptionKey);
|
newCollection,
|
||||||
|
token
|
||||||
|
);
|
||||||
|
createdCollection = await getCollectionSecrets(
|
||||||
|
createdCollection,
|
||||||
|
encryptionKey
|
||||||
|
);
|
||||||
return createdCollection;
|
return createdCollection;
|
||||||
}
|
};
|
||||||
|
|
||||||
const createCollection = async (collectionData: collection, token: string): Promise<collection> => {
|
const createCollection = async (
|
||||||
|
collectionData: collection,
|
||||||
|
token: string
|
||||||
|
): Promise<collection> => {
|
||||||
try {
|
try {
|
||||||
const response = await HTTPService.post(`${ENDPOINT}/collections`, collectionData, null, { 'X-Auth-Token': token });
|
const response = await HTTPService.post(
|
||||||
|
`${ENDPOINT}/collections`,
|
||||||
|
collectionData,
|
||||||
|
null,
|
||||||
|
{ 'X-Auth-Token': token }
|
||||||
|
);
|
||||||
return response.data.collection;
|
return response.data.collection;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("create Collection failed " + e);
|
console.log('create Collection failed ' + e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export const addToFavorites = async (file: file) => {
|
export const addToFavorites = async (file: file) => {
|
||||||
let favCollection: collection = (await localForage.getItem<collection>('fav-collection'))[0];
|
let favCollection: collection = await localForage.getItem<collection>(
|
||||||
|
FAV_COLLECTION
|
||||||
|
);
|
||||||
if (!favCollection) {
|
if (!favCollection) {
|
||||||
favCollection = await AddCollection("Favorites", CollectionType.favorites);
|
favCollection = await AddCollection(
|
||||||
await localForage.setItem('fav-collection', favCollection);
|
'Favorites',
|
||||||
|
CollectionType.favorites
|
||||||
|
);
|
||||||
|
await localForage.setItem(FAV_COLLECTION, favCollection);
|
||||||
}
|
}
|
||||||
await addtoCollection(favCollection, [file])
|
await addToCollection(favCollection, [file]);
|
||||||
}
|
};
|
||||||
|
|
||||||
export const removeFromFavorites = async (file: file) => {
|
export const removeFromFavorites = async (file: file) => {
|
||||||
let favCollection: collection = (await localForage.getItem<collection>('fav-collection'))[0];
|
let favCollection: collection = await localForage.getItem<collection>(
|
||||||
await removeFromCollection(favCollection, [file])
|
FAV_COLLECTION
|
||||||
}
|
);
|
||||||
|
await removeFromCollection(favCollection, [file]);
|
||||||
|
};
|
||||||
|
|
||||||
const addtoCollection = async (collection: collection, files: file[]) => {
|
const addToCollection = async (collection: collection, files: file[]) => {
|
||||||
try {
|
try {
|
||||||
const params = new Object();
|
const params = new Object();
|
||||||
const worker = await new CryptoWorker();
|
const worker = await new CryptoWorker();
|
||||||
const token = getToken();
|
const token = getToken();
|
||||||
params["collectionID"] = collection.id;
|
params['collectionID'] = collection.id;
|
||||||
await Promise.all(files.map(async file => {
|
await Promise.all(
|
||||||
file.collectionID = Number(collection.id);
|
files.map(async (file) => {
|
||||||
const newEncryptedKey: keyEncryptionResult = await worker.encryptToB64(file.key, collection.key);
|
file.collectionID = collection.id;
|
||||||
file.encryptedKey = newEncryptedKey.encryptedData;
|
const newEncryptedKey: keyEncryptionResult = await worker.encryptToB64(
|
||||||
file.keyDecryptionNonce = newEncryptedKey.nonce;
|
file.key,
|
||||||
if (params["files"] == undefined) {
|
collection.key
|
||||||
params["files"] = [];
|
);
|
||||||
}
|
file.encryptedKey = newEncryptedKey.encryptedData;
|
||||||
params["files"].push({
|
file.keyDecryptionNonce = newEncryptedKey.nonce;
|
||||||
id: file.id,
|
if (params['files'] == undefined) {
|
||||||
encryptedKey: file.encryptedKey,
|
params['files'] = [];
|
||||||
keyDecryptionNonce: file.keyDecryptionNonce
|
}
|
||||||
|
params['files'].push({
|
||||||
|
id: file.id,
|
||||||
|
encryptedKey: file.encryptedKey,
|
||||||
|
keyDecryptionNonce: file.keyDecryptionNonce,
|
||||||
|
});
|
||||||
|
return file;
|
||||||
})
|
})
|
||||||
return file;
|
);
|
||||||
}));
|
await HTTPService.post(
|
||||||
await HTTPService.post(`${ENDPOINT}/collections/add-files`, params, null, { 'X-Auth-Token': token });
|
`${ENDPOINT}/collections/add-files`,
|
||||||
|
params,
|
||||||
|
null,
|
||||||
|
{ 'X-Auth-Token': token }
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Add to collection Failed " + e);
|
console.log('Add to collection Failed ' + e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
const removeFromCollection = async (collection: collection, files: file[]) => {
|
const removeFromCollection = async (collection: collection, files: file[]) => {
|
||||||
try {
|
try {
|
||||||
const params = new Object();
|
const params = new Object();
|
||||||
const token = getToken();
|
const token = getToken();
|
||||||
params["collectionID"] = collection.id;
|
params['collectionID'] = collection.id;
|
||||||
await Promise.all(files.map(async file => {
|
await Promise.all(
|
||||||
if (params["fileIDs"] == undefined) {
|
files.map(async (file) => {
|
||||||
params["fileIDs"] = [];
|
if (params['fileIDs'] == undefined) {
|
||||||
}
|
params['fileIDs'] = [];
|
||||||
params["fileIDs"].push(file.id);
|
}
|
||||||
}));
|
params['fileIDs'].push(file.id);
|
||||||
await HTTPService.post(`${ENDPOINT}/collections/remove-files`, params, null, { 'X-Auth-Token': token });
|
})
|
||||||
|
);
|
||||||
|
await HTTPService.post(
|
||||||
|
`${ENDPOINT}/collections/remove-files`,
|
||||||
|
params,
|
||||||
|
null,
|
||||||
|
{ 'X-Auth-Token': token }
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("remove from collection failed " + e);
|
console.log('remove from collection failed ' + e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const setLocalFavoriteCollection = async (collections: collection[]) => {
|
||||||
|
const localFavCollection = await localForage.getItem(FAV_COLLECTION);
|
||||||
|
if (localFavCollection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const favCollection = collections.filter(
|
||||||
|
(collection) => collection.type == CollectionType.favorites
|
||||||
|
);
|
||||||
|
if (favCollection.length > 0) {
|
||||||
|
await localForage.setItem(FAV_COLLECTION, favCollection[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -16,6 +16,8 @@ localForage.config({
|
||||||
storeName: 'files',
|
storeName: 'files',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const FILES = 'files';
|
||||||
|
|
||||||
export interface fileAttribute {
|
export interface fileAttribute {
|
||||||
encryptedData: Uint8Array | string;
|
encryptedData: Uint8Array | string;
|
||||||
decryptionHeader: string;
|
decryptionHeader: string;
|
||||||
|
@ -29,7 +31,6 @@ export interface user {
|
||||||
email: string;
|
email: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface file {
|
export interface file {
|
||||||
id: number;
|
id: number;
|
||||||
collectionID: number;
|
collectionID: number;
|
||||||
|
@ -49,92 +50,95 @@ export interface file {
|
||||||
updationTime: number;
|
updationTime: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const syncData = async (token, collections) => {
|
||||||
|
const { files: resp, isUpdated } = await syncFiles(token, collections);
|
||||||
|
|
||||||
|
return {
|
||||||
export const fetchData = async (token, collections) => {
|
data: resp.map((item) => ({
|
||||||
const resp = await fetchFiles(
|
|
||||||
token,
|
|
||||||
collections
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
resp.map((item) => ({
|
|
||||||
...item,
|
...item,
|
||||||
w: window.innerWidth,
|
w: window.innerWidth,
|
||||||
h: window.innerHeight,
|
h: window.innerHeight,
|
||||||
}))
|
})),
|
||||||
);
|
isUpdated,
|
||||||
}
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const localFiles = async () => {
|
export const localFiles = async () => {
|
||||||
let files: Array<file> = (await localForage.getItem<file[]>('files')) || [];
|
let files: Array<file> = (await localForage.getItem<file[]>(FILES)) || [];
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchFiles = async (
|
|
||||||
token: string,
|
|
||||||
collections: collection[]
|
|
||||||
) => {
|
|
||||||
let files = await localFiles();
|
|
||||||
const collectionUpdationTime = new Map<string, string>();
|
|
||||||
let fetchedFiles = [];
|
|
||||||
for (let collection of collections) {
|
|
||||||
const files = await getFiles(collection, null, 100, token);
|
|
||||||
fetchedFiles.push(...files);
|
|
||||||
collectionUpdationTime.set(collection.id, files.length > 0 ? files.slice(-1)[0].updationTime.toString() : "0");
|
|
||||||
}
|
|
||||||
files.push(...fetchedFiles);
|
|
||||||
var latestFiles = new Map<string, file>();
|
|
||||||
files.forEach((file) => {
|
|
||||||
let uid = `${file.collectionID}-${file.id}`;
|
|
||||||
if (!latestFiles.has(uid) || latestFiles.get(uid).updationTime < file.updationTime) {
|
|
||||||
latestFiles.set(uid, file);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
files = [];
|
|
||||||
for (const [_, file] of latestFiles) {
|
|
||||||
if (!file.isDeleted)
|
|
||||||
files.push(file);
|
|
||||||
}
|
|
||||||
files = files.sort(
|
|
||||||
(a, b) => b.metadata.creationTime - a.metadata.creationTime
|
|
||||||
);
|
|
||||||
await localForage.setItem('files', files);
|
|
||||||
for (let [collectionID, updationTime] of collectionUpdationTime) {
|
|
||||||
await localForage.setItem(`${collectionID}-time`, updationTime);
|
|
||||||
}
|
|
||||||
let updationTime = await localForage.getItem('collection-update-time') as number;
|
|
||||||
for (let collection of collections) {
|
|
||||||
updationTime = Math.max(updationTime, collection.updationTime);
|
|
||||||
}
|
|
||||||
await localForage.setItem('collection-update-time', updationTime);
|
|
||||||
return files;
|
return files;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFiles = async (collection: collection, sinceTime: string, limit: number, token: string): Promise<file[]> => {
|
export const syncFiles = async (token: string, collections: collection[]) => {
|
||||||
|
let files = await localFiles();
|
||||||
|
let isUpdated = false;
|
||||||
|
files = await removeDeletedCollectionFiles(collections, files);
|
||||||
|
for (let collection of collections) {
|
||||||
|
const lastSyncTime =
|
||||||
|
(await localForage.getItem<number>(`${collection.id}-time`)) ?? 0;
|
||||||
|
if (collection.updationTime === lastSyncTime) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
isUpdated = true;
|
||||||
|
let fetchedFiles =
|
||||||
|
(await getFiles(collection, lastSyncTime, 100, token)) ?? [];
|
||||||
|
files.push(...fetchedFiles);
|
||||||
|
var latestVersionFiles = new Map<number, file>();
|
||||||
|
files.forEach((file) => {
|
||||||
|
if (
|
||||||
|
!latestVersionFiles.has(file.id) ||
|
||||||
|
latestVersionFiles.get(file.id).updationTime < file.updationTime
|
||||||
|
) {
|
||||||
|
latestVersionFiles.set(file.id, file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
files = [];
|
||||||
|
for (const [_, file] of latestVersionFiles) {
|
||||||
|
if (file.isDeleted) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
files.push(file);
|
||||||
|
}
|
||||||
|
files = files.sort(
|
||||||
|
(a, b) => b.metadata.creationTime - a.metadata.creationTime
|
||||||
|
);
|
||||||
|
await localForage.setItem('files', files);
|
||||||
|
await localForage.setItem(
|
||||||
|
`${collection.id}-time`,
|
||||||
|
collection.updationTime
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return { files, isUpdated };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFiles = async (
|
||||||
|
collection: collection,
|
||||||
|
sinceTime: number,
|
||||||
|
limit: number,
|
||||||
|
token: string
|
||||||
|
): Promise<file[]> => {
|
||||||
try {
|
try {
|
||||||
const worker = await new CryptoWorker();
|
const worker = await new CryptoWorker();
|
||||||
let promises: Promise<file>[] = [];
|
let promises: Promise<file>[] = [];
|
||||||
if (collection.isDeleted) {
|
|
||||||
// TODO: Remove files in this collection from localForage and cache
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let time =
|
let time =
|
||||||
sinceTime || (await localForage.getItem<string>(`${collection.id}-time`)) || "0";
|
sinceTime ||
|
||||||
|
(await localForage.getItem<number>(`${collection.id}-time`)) ||
|
||||||
|
0;
|
||||||
let resp;
|
let resp;
|
||||||
do {
|
do {
|
||||||
resp = await HTTPService.get(`${ENDPOINT}/collections/diff`, {
|
resp = await HTTPService.get(
|
||||||
collectionID: collection.id,
|
`${ENDPOINT}/collections/diff`,
|
||||||
sinceTime: time,
|
|
||||||
limit: limit.toString(),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
'X-Auth-Token': token
|
collectionID: collection.id.toString(),
|
||||||
});
|
sinceTime: time.toString(),
|
||||||
promises.push(...resp.data.diff.map(
|
limit: limit.toString(),
|
||||||
async (file: file) => {
|
},
|
||||||
|
{
|
||||||
|
'X-Auth-Token': token,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
promises.push(
|
||||||
|
...resp.data.diff.map(async (file: file) => {
|
||||||
if (!file.isDeleted) {
|
if (!file.isDeleted) {
|
||||||
|
|
||||||
file.key = await worker.decryptB64(
|
file.key = await worker.decryptB64(
|
||||||
file.encryptedKey,
|
file.encryptedKey,
|
||||||
file.keyDecryptionNonce,
|
file.keyDecryptionNonce,
|
||||||
|
@ -143,8 +147,8 @@ export const getFiles = async (collection: collection, sinceTime: string, limit:
|
||||||
file.metadata = await worker.decryptMetadata(file);
|
file.metadata = await worker.decryptMetadata(file);
|
||||||
}
|
}
|
||||||
return file;
|
return file;
|
||||||
}
|
})
|
||||||
));
|
);
|
||||||
|
|
||||||
if (resp.data.diff.length) {
|
if (resp.data.diff.length) {
|
||||||
time = resp.data.diff.slice(-1)[0].updationTime.toString();
|
time = resp.data.diff.slice(-1)[0].updationTime.toString();
|
||||||
|
@ -152,9 +156,9 @@ export const getFiles = async (collection: collection, sinceTime: string, limit:
|
||||||
} while (resp.data.diff.length === limit);
|
} while (resp.data.diff.length === limit);
|
||||||
return await Promise.all(promises);
|
return await Promise.all(promises);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Get files failed" + e);
|
console.log('Get files failed' + e);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
export const getPreview = async (token: string, file: file) => {
|
export const getPreview = async (token: string, file: file) => {
|
||||||
try {
|
try {
|
||||||
const cache = await caches.open('thumbs');
|
const cache = await caches.open('thumbs');
|
||||||
|
@ -175,13 +179,16 @@ export const getPreview = async (token: string, file: file) => {
|
||||||
file.key
|
file.key
|
||||||
);
|
);
|
||||||
try {
|
try {
|
||||||
await cache.put(file.id.toString(), new Response(new Blob([decrypted])));
|
await cache.put(
|
||||||
|
file.id.toString(),
|
||||||
|
new Response(new Blob([decrypted]))
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// TODO: handle storage full exception.
|
// TODO: handle storage full exception.
|
||||||
}
|
}
|
||||||
return URL.createObjectURL(new Blob([decrypted]));
|
return URL.createObjectURL(new Blob([decrypted]));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("get preview Failed" + e);
|
console.log('get preview Failed' + e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,9 +207,19 @@ export const getFile = async (token: string, file: file) => {
|
||||||
file.key
|
file.key
|
||||||
);
|
);
|
||||||
return URL.createObjectURL(new Blob([decrypted]));
|
return URL.createObjectURL(new Blob([decrypted]));
|
||||||
}
|
} catch (e) {
|
||||||
catch (e) {
|
console.log('get file failed ' + e);
|
||||||
console.log("get file failed " + e);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const removeDeletedCollectionFiles = async (
|
||||||
|
collections: collection[],
|
||||||
|
files: file[]
|
||||||
|
) => {
|
||||||
|
const syncedCollectionIds = new Set<number>();
|
||||||
|
for (let collection of collections) {
|
||||||
|
syncedCollectionIds.add(collection.id);
|
||||||
|
}
|
||||||
|
files = files.filter((file) => syncedCollectionIds.has(file.collectionID));
|
||||||
|
return files;
|
||||||
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@ import HTTPService from './HTTPService';
|
||||||
import * as Comlink from 'comlink';
|
import * as Comlink from 'comlink';
|
||||||
import EXIF from "exif-js";
|
import EXIF from "exif-js";
|
||||||
import { fileAttribute } from './fileService';
|
import { fileAttribute } from './fileService';
|
||||||
import { collection, collectionLatestFile } from "./collectionService"
|
import { collection, CollectionAndItsLatestFile } from "./collectionService"
|
||||||
import { FILE_TYPE } from 'pages/gallery';
|
import { FILE_TYPE } from 'pages/gallery';
|
||||||
const CryptoWorker: any =
|
const CryptoWorker: any =
|
||||||
typeof window !== 'undefined' &&
|
typeof window !== 'undefined' &&
|
||||||
|
@ -49,7 +49,7 @@ interface objectKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface uploadFile extends objectKeys {
|
interface uploadFile extends objectKeys {
|
||||||
collectionID: string,
|
collectionID: number,
|
||||||
encryptedKey: string;
|
encryptedKey: string;
|
||||||
keyDecryptionNonce: string;
|
keyDecryptionNonce: string;
|
||||||
metadata?: {
|
metadata?: {
|
||||||
|
@ -80,7 +80,7 @@ class UploadService {
|
||||||
private totalFilesCount: number
|
private totalFilesCount: number
|
||||||
private metadataMap: Map<string, Object>;
|
private metadataMap: Map<string, Object>;
|
||||||
|
|
||||||
public async uploadFiles(recievedFiles: File[], collectionLatestFile: collectionLatestFile, token: string, progressBarProps) {
|
public async uploadFiles(recievedFiles: File[], collectionAndItsLatestFile: CollectionAndItsLatestFile, token: string, progressBarProps) {
|
||||||
try {
|
try {
|
||||||
const worker = await new CryptoWorker();
|
const worker = await new CryptoWorker();
|
||||||
this.stepsCompleted = 0;
|
this.stepsCompleted = 0;
|
||||||
|
@ -107,7 +107,7 @@ class UploadService {
|
||||||
while (actualFiles.length > 0) {
|
while (actualFiles.length > 0) {
|
||||||
var promises = [];
|
var promises = [];
|
||||||
for (var i = 0; i < 5 && actualFiles.length > 0; i++)
|
for (var i = 0; i < 5 && actualFiles.length > 0; i++)
|
||||||
promises.push(this.uploadHelper(progressBarProps, actualFiles.pop(), collectionLatestFile.collection, token));
|
promises.push(this.uploadHelper(progressBarProps, actualFiles.pop(), collectionAndItsLatestFile.collection, token));
|
||||||
uploadFilesWithoutMetaData.push(...await Promise.all(promises));
|
uploadFilesWithoutMetaData.push(...await Promise.all(promises));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +364,6 @@ class UploadService {
|
||||||
resolve(blob);
|
resolve(blob);
|
||||||
}), 'image/jpeg', 0.4
|
}), 'image/jpeg', 0.4
|
||||||
});
|
});
|
||||||
console.log(URL.createObjectURL(thumbnailBlob));
|
|
||||||
const thumbnail = this.getUint8ArrayView(thumbnailBlob);
|
const thumbnail = this.getUint8ArrayView(thumbnailBlob);
|
||||||
return thumbnail;
|
return thumbnail;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
export const getEndpoint = () => {
|
export const getEndpoint = () => {
|
||||||
const endPoint = process.env.NEXT_PUBLIC_ENTE_ENDPOINT ?? "https://api.ente.io";
|
const endPoint = process.env.NEXT_PUBLIC_ENTE_ENDPOINT ?? "https://api.ente.io";
|
||||||
console.log(endPoint);
|
|
||||||
return endPoint;
|
return endPoint;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue