Merge branch 'main' into folder-plus-file-drop

This commit is contained in:
Abhinav 2022-12-16 14:25:00 +05:30
commit 3665d9d4a5
17 changed files with 115 additions and 85 deletions

View file

@ -12,9 +12,6 @@ export default function CollectionSortOptions(props: CollectionSortProps) {
<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>

View file

@ -15,7 +15,7 @@ import {
import { ManageDownloadAccess } from './downloadAccess';
import { handleSharingErrors } from 'utils/error/ui';
import { SetPublicShareProp } from 'types/publicCollection';
// import { ManagePublicCollect } from './publicCollect';
import { ManagePublicCollect } from './publicCollect';
interface Iprops {
publicShareProp: PublicURL;
@ -77,6 +77,13 @@ export default function PublicShareManage({
updatePublicShareURLHelper
}
/>
<ManagePublicCollect
collection={collection}
publicShareProp={publicShareProp}
updatePublicShareURLHelper={
updatePublicShareURLHelper
}
/>
<ManageDownloadAccess
collection={collection}
publicShareProp={publicShareProp}
@ -91,13 +98,6 @@ export default function PublicShareManage({
updatePublicShareURLHelper
}
/>
{/* <ManagePublicCollect
collection={collection}
publicShareProp={publicShareProp}
updatePublicShareURLHelper={
updatePublicShareURLHelper
}
/> */}
</Stack>
{sharableLinkError && (
<Typography

View file

@ -1,6 +1,5 @@
import { Box, Typography } from '@mui/material';
import { AppContext } from 'pages/_app';
import React, { useContext } from 'react';
import React from 'react';
import { PublicURL, Collection, UpdatePublicURL } from 'types/collection';
import constants from 'utils/strings/constants';
import PublicShareSwitch from '../switch';
@ -16,35 +15,13 @@ export function ManagePublicCollect({
updatePublicShareURLHelper,
collection,
}: Iprops) {
const appContext = useContext(AppContext);
const handleFileDownloadSetting = () => {
if (!publicShareProp.enableCollect) {
enablePublicCollect();
} else {
updatePublicShareURLHelper({
collectionID: collection.id,
enableCollect: false,
enableCollect: !publicShareProp.enableCollect,
});
}
};
const enablePublicCollect = () => {
appContext.setDialogMessage({
title: constants.ENABLE_PUBLIC_COLLECT,
content: constants.ENABLE_PUBLIC_COLLECT_MESSAGE(),
close: { text: constants.CANCEL },
proceed: {
text: constants.ENABLE,
action: () =>
updatePublicShareURLHelper({
collectionID: collection.id,
enableCollect: true,
}),
variant: 'accent',
},
});
};
return (
<Box>
<Typography mb={0.5}>{constants.PUBLIC_COLLECT}</Typography>

View file

@ -28,6 +28,7 @@ export interface SingleInputFormProps {
hiddenPostInput?: any;
autoComplete?: string;
blockButton?: boolean;
hiddenLabel?: boolean;
}
export default function SingleInputForm(props: SingleInputFormProps) {
@ -88,12 +89,15 @@ export default function SingleInputForm(props: SingleInputFormProps) {
<form noValidate onSubmit={handleSubmit}>
{props.hiddenPreInput}
<TextField
hiddenLabel={props.hiddenLabel}
variant="filled"
fullWidth
type={showPassword ? 'text' : props.fieldType}
id={props.fieldType}
name={props.fieldType}
label={props.placeholder}
{...(props.hiddenLabel
? { placeholder: props.placeholder }
: { label: props.placeholder })}
value={values.inputValue}
onChange={handleChange('inputValue')}
error={Boolean(errors.inputValue)}

View file

@ -86,6 +86,12 @@ interface Props {
}
export default function Uploader(props: Props) {
const appContext = useContext(AppContext);
const galleryContext = useContext(GalleryContext);
const publicCollectionGalleryContext = useContext(
PublicCollectionGalleryContext
);
const [uploadProgressView, setUploadProgressView] = useState(false);
const [uploadStage, setUploadStage] = useState<UPLOAD_STAGES>(
UPLOAD_STAGES.START
@ -109,8 +115,8 @@ export default function Uploader(props: Props) {
const [importSuggestion, setImportSuggestion] = useState<ImportSuggestion>(
DEFAULT_IMPORT_SUGGESTION
);
const appContext = useContext(AppContext);
const galleryContext = useContext(GalleryContext);
const [electronFiles, setElectronFiles] = useState<ElectronFile[]>(null);
const [webFiles, setWebFiles] = useState([]);
const toUploadFiles = useRef<File[] | ElectronFile[]>(null);
const isPendingDesktopUpload = useRef(false);
@ -119,23 +125,17 @@ export default function Uploader(props: Props) {
const pickedUploadType = useRef<PICKED_UPLOAD_TYPE>(null);
const zipPaths = useRef<string[]>(null);
const currentUploadPromise = useRef<Promise<void>>(null);
const [electronFiles, setElectronFiles] = useState<ElectronFile[]>(null);
const [webFiles, setWebFiles] = useState([]);
const uploadRunning = useRef(false);
const uploaderNameRef = useRef<string>(null);
const closeUploadProgress = () => setUploadProgressView(false);
const showUserNameInputDialog = () => setUserNameInputDialogView(true);
const closeUserNameInputDialog = () => setUserNameInputDialogView(false);
const setCollectionName = (collectionName: string) => {
isPendingDesktopUpload.current = true;
pendingDesktopUploadCollectionName.current = collectionName;
};
const uploadRunning = useRef(false);
const publicCollectionGalleryContext = useContext(
PublicCollectionGalleryContext
);
const handleChoiceModalClose = () => {
setChoiceModalView(false);
uploadRunning.current = false;
@ -144,6 +144,11 @@ export default function Uploader(props: Props) {
uploadRunning.current = false;
};
const handleUserNameInputDialogClose = () => {
setUserNameInputDialogView(false);
uploadRunning.current = false;
};
useEffect(() => {
uploadManager.init(
{
@ -308,7 +313,6 @@ export default function Uploader(props: Props) {
[collection],
uploaderName
);
toUploadFiles.current = null;
} catch (e) {
logError(e, 'Failed to upload files to existing collections');
}
@ -470,11 +474,13 @@ export default function Uploader(props: Props) {
try {
addLogLine('user retrying failed upload');
const filesWithCollections =
await uploadManager.getFailedFilesWithCollections();
uploadManager.getFailedFilesWithCollections();
const uploaderName = uploadManager.getUploaderName();
await preUploadAction();
await uploadManager.queueFilesForUpload(
filesWithCollections.files,
filesWithCollections.collections
filesWithCollections.collections,
uploaderName
);
} catch (err) {
showUserFacingError(err.message);
@ -546,11 +552,8 @@ export default function Uploader(props: Props) {
const uploaderName = await getPublicCollectionUploaderName(
getPublicCollectionUID(publicCollectionGalleryContext.token)
);
if (!uploaderName) {
uploaderNameRef.current = uploaderName;
showUserNameInputDialog();
} else {
await handlePublicUpload(uploaderName, true);
}
return;
}
if (isPendingDesktopUpload.current) {
@ -709,8 +712,10 @@ export default function Uploader(props: Props) {
/>
<UserNameInputDialog
open={userNameInputDialogView}
onClose={closeUserNameInputDialog}
onClose={handleUserNameInputDialogClose}
onNameSubmit={handlePublicUpload}
toUploadFilesCount={toUploadFiles.current?.length}
uploaderName={uploaderNameRef.current}
/>
</>
);

View file

@ -5,7 +5,13 @@ import AutoAwesomeOutlinedIcon from '@mui/icons-material/AutoAwesomeOutlined';
import { Typography } from '@mui/material';
import SingleInputForm from './SingleInputForm';
export default function UserNameInputDialog({ open, onClose, onNameSubmit }) {
export default function UserNameInputDialog({
open,
onClose,
onNameSubmit,
toUploadFilesCount,
uploaderName,
}) {
const handleSubmit = async (inputValue: string) => {
onClose();
await onNameSubmit(inputValue);
@ -23,12 +29,14 @@ export default function UserNameInputDialog({ open, onClose, onNameSubmit }) {
{constants.PUBLIC_UPLOADER_NAME_MESSAGE}
</Typography>
<SingleInputForm
hiddenLabel
initialValue={uploaderName}
callback={handleSubmit}
placeholder={constants.ENTER_FILE_NAME}
buttonText={constants.CONTINUE}
placeholder={constants.NAME_PLACEHOLDER}
buttonText={constants.ADD_X_PHOTOS(toUploadFilesCount)}
fieldType="text"
blockButton
secondaryButtonAction={() => {}}
secondaryButtonAction={onClose}
/>
</DialogBox>
);

View file

@ -21,7 +21,6 @@ export enum CollectionSummaryType {
export enum COLLECTION_SORT_BY {
NAME,
CREATION_TIME_ASCENDING,
CREATION_TIME_DESCENDING,
UPDATION_TIME_DESCENDING,
}

View file

@ -736,11 +736,6 @@ export function sortCollectionSummaries(
return collectionSummaries
.sort((a, b) => {
switch (sortBy) {
case COLLECTION_SORT_BY.CREATION_TIME_DESCENDING:
return compareCollectionsLatestFile(
b.latestFile,
a.latestFile
);
case COLLECTION_SORT_BY.CREATION_TIME_ASCENDING:
return (
-1 *

View file

@ -22,6 +22,7 @@ import {
getUint8ArrayView,
} from '../readerService';
import { generateThumbnail } from './thumbnailService';
import { EncryptedMagicMetadataCore } from 'types/magicMetadata';
const EDITED_FILE_SUFFIX = '-edited';
@ -110,6 +111,16 @@ export async function encryptFile(
const { file: encryptedMetadata }: EncryptionResult =
await worker.encryptMetadata(file.metadata, fileKey);
const { file: encryptedPubMagicMetadataData }: EncryptionResult =
await worker.encryptMetadata(file.pubMagicMetadata.data, fileKey);
const encryptedPubMagicMetadata: EncryptedMagicMetadataCore = {
version: file.pubMagicMetadata.version,
count: file.pubMagicMetadata.count,
data: encryptedPubMagicMetadataData.encryptedData as unknown as string,
header: encryptedPubMagicMetadataData.decryptionHeader,
};
const encryptedKey: B64EncryptionResult = await worker.encryptToB64(
fileKey,
encryptionKey
@ -120,6 +131,7 @@ export async function encryptFile(
file: encryptedFiledata,
thumbnail: encryptedThumbnail,
metadata: encryptedMetadata,
pubMagicMetadata: encryptedPubMagicMetadata,
localID: file.localID,
},
fileKey: encryptedKey,

View file

@ -0,0 +1,17 @@
import {
FilePublicMagicMetadataProps,
FilePublicMagicMetadata,
} from 'types/file';
import { NEW_FILE_MAGIC_METADATA } from 'types/magicMetadata';
import { updateMagicMetadataProps } from 'utils/magicMetadata';
export async function constructPublicMagicMetadata(
publicMagicMetadataProps: FilePublicMagicMetadataProps
): Promise<FilePublicMagicMetadata> {
const pubMagicMetadata = await updateMagicMetadataProps(
NEW_FILE_MAGIC_METADATA,
null,
publicMagicMetadataProps
);
return pubMagicMetadata;
}

View file

@ -389,13 +389,17 @@ class UploadManager {
uploadCancelService.requestUploadCancelation();
}
async getFailedFilesWithCollections() {
getFailedFilesWithCollections() {
return {
files: this.failedFiles,
collections: [...this.collections.values()],
};
}
getUploaderName() {
return this.uploaderName;
}
private updateExistingFiles(decryptedFile: EnteFile) {
if (!decryptedFile) {
throw Error("decrypted file can't be undefined");

View file

@ -34,6 +34,8 @@ import { uploadStreamUsingMultipart } from './multiPartUploadService';
import UIService from './uiService';
import { USE_CF_PROXY } from 'constants/upload';
import publicUploadHttpClient from './publicUploadHttpClient';
import { constructPublicMagicMetadata } from './magicMetadataService';
import { FilePublicMagicMetadataProps } from 'types/file';
class UploadService {
private uploadURLs: UploadURL[] = [];
@ -127,6 +129,12 @@ class UploadService {
return clusterLivePhotoFiles(mediaFiles);
}
constructPublicMagicMetadata(
publicMagicMetadataProps: FilePublicMagicMetadataProps
) {
return constructPublicMagicMetadata(publicMagicMetadataProps);
}
async encryptAsset(
worker: any,
file: FileWithMetadata,
@ -188,6 +196,7 @@ class UploadService {
objectKey: thumbnailObjectKey,
},
metadata: file.metadata,
pubMagicMetadata: file.pubMagicMetadata,
};
return backupedFile;
} catch (e) {

View file

@ -1,4 +1,4 @@
import { EnteFile } from 'types/file';
import { EnteFile, FilePublicMagicMetadata } from 'types/file';
import { handleUploadError, CustomError } from 'utils/error';
import { logError } from 'utils/sentry';
import { findMatchingExistingFiles } from 'utils/upload';
@ -10,6 +10,7 @@ import {
FileWithCollection,
BackupedFile,
UploadFile,
FileWithMetadata,
FileTypeInfo,
} from 'types/upload';
import { addLocalLog, addLogLine } from 'utils/logging';
@ -17,6 +18,7 @@ import { convertBytesToHumanReadable } from 'utils/file/size';
import { sleep } from 'utils/common';
import { addToCollection } from 'services/collectionService';
import uploadCancelService from './uploadCancelService';
import uploadService from './uploadService';
interface UploadResponse {
fileUploadResult: UPLOAD_RESULT;
@ -118,14 +120,18 @@ export default async function uploader(
if (file.hasStaticThumbnail) {
metadata.hasStaticThumbnail = true;
}
let pubMagicMetadata: FilePublicMagicMetadata;
if (uploaderName) {
metadata.uploaderName = uploaderName;
pubMagicMetadata = await uploadService.constructPublicMagicMetadata(
{ uploaderName }
);
}
const fileWithMetadata = {
const fileWithMetadata: FileWithMetadata = {
localID,
filedata: file.filedata,
thumbnail: file.thumbnail,
metadata,
pubMagicMetadata,
};
if (uploadCancelService.isUploadCancelationRequested()) {

View file

@ -20,6 +20,7 @@ export interface FilePublicMagicMetadataProps {
editedTime?: number;
editedName?: string;
caption?: string;
uploaderName?: string;
}
export interface FilePublicMagicMetadata

View file

@ -21,7 +21,7 @@ export enum SUB_TYPE {
}
export const NEW_FILE_MAGIC_METADATA: MagicMetadataCore = {
version: 0,
version: 1,
data: {},
header: null,
count: 0,

View file

@ -1,6 +1,7 @@
import { FILE_TYPE } from 'constants/file';
import { Collection } from 'types/collection';
import { fileAttribute } from 'types/file';
import { fileAttribute, FilePublicMagicMetadata } from 'types/file';
import { EncryptedMagicMetadataCore } from 'types/magicMetadata';
export interface DataStream {
stream: ReadableStream<Uint8Array>;
@ -27,7 +28,6 @@ export interface Metadata {
hash?: string;
imageHash?: string;
videoHash?: string;
uploaderName?: string;
}
export interface Location {
@ -114,6 +114,7 @@ export interface FileWithMetadata
extends Omit<FileInMemory, 'hasStaticThumbnail'> {
metadata: Metadata;
localID: number;
pubMagicMetadata: FilePublicMagicMetadata;
}
export interface EncryptedFile {
@ -124,6 +125,7 @@ export interface ProcessedFile {
file: fileAttribute;
thumbnail: fileAttribute;
metadata: fileAttribute;
pubMagicMetadata: EncryptedMagicMetadataCore;
localID: number;
}
export interface BackupedFile extends Omit<ProcessedFile, 'localID'> {}

View file

@ -685,7 +685,7 @@ const englishConstants = {
'Are you sure you want to disable public sharing?',
FILE_DOWNLOAD: 'Allow downloads',
LINK_PASSWORD_LOCK: 'Password lock',
PUBLIC_COLLECT: 'Public collect',
PUBLIC_COLLECT: 'Allow adding photos',
LINK_DEVICE_LIMIT: 'Device limit',
LINK_EXPIRY: 'Link expiry',
LINK_EXPIRY_NEVER: 'Never',
@ -698,17 +698,10 @@ const englishConstants = {
</p>{' '}
<p>
Viewers can still take screenshots or save a copy of your photos
using external tools'{' '}
using external tools{' '}
</p>
</>
),
ENABLE_PUBLIC_COLLECT: 'Enable public collect',
ENABLE_PUBLIC_COLLECT_MESSAGE: () => (
<>
<p>Are you sure that you want to enable public collect? </p>{' '}
<p>Uploaded files will be counted towards your storage</p>
</>
),
ABUSE_REPORT: 'Abuse report',
ABUSE_REPORT_BUTTON_TEXT: 'Report abuse?',
MALICIOUS_CONTENT: 'Contains malicious content',
@ -890,6 +883,7 @@ const englishConstants = {
</p>
</>
),
ADD_X_PHOTOS: (x: number) => `Add ${x} ${x > 1 ? 'photos' : 'photo'}`,
};
export default englishConstants;