commit
49ad023412
|
@ -9,7 +9,7 @@ import constants from 'utils/strings/constants';
|
||||||
import DialogBoxBase from 'components/DialogBox/base';
|
import DialogBoxBase from 'components/DialogBox/base';
|
||||||
import DialogTitleWithCloseButton from 'components/DialogBox/titleWithCloseButton';
|
import DialogTitleWithCloseButton from 'components/DialogBox/titleWithCloseButton';
|
||||||
import UploadStrategyChoiceModal from 'components/pages/gallery/UploadStrategyChoiceModal';
|
import UploadStrategyChoiceModal from 'components/pages/gallery/UploadStrategyChoiceModal';
|
||||||
import { UPLOAD_STRATEGY } from 'components/pages/gallery/Upload';
|
import { UPLOAD_STRATEGY } from 'constants/upload';
|
||||||
|
|
||||||
interface Iprops {
|
interface Iprops {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
|
|
@ -33,7 +33,7 @@ import {
|
||||||
SegregatedFinishedUploads,
|
SegregatedFinishedUploads,
|
||||||
InProgressUpload,
|
InProgressUpload,
|
||||||
} from 'types/upload/ui';
|
} from 'types/upload/ui';
|
||||||
import { UPLOAD_STAGES } from 'constants/upload';
|
import { UPLOAD_STAGES, UPLOAD_STRATEGY } from 'constants/upload';
|
||||||
|
|
||||||
const FIRST_ALBUM_NAME = 'My First Album';
|
const FIRST_ALBUM_NAME = 'My First Album';
|
||||||
|
|
||||||
|
@ -59,11 +59,6 @@ interface Props {
|
||||||
showSessionExpiredMessage: () => void;
|
showSessionExpiredMessage: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum UPLOAD_STRATEGY {
|
|
||||||
SINGLE_COLLECTION,
|
|
||||||
COLLECTION_PER_FOLDER,
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum DESKTOP_UPLOAD_TYPE {
|
export enum DESKTOP_UPLOAD_TYPE {
|
||||||
FILES = 'files',
|
FILES = 'files',
|
||||||
FOLDERS = 'folders',
|
FOLDERS = 'folders',
|
||||||
|
|
|
@ -31,6 +31,11 @@ export enum UPLOAD_STAGES {
|
||||||
FINISH,
|
FINISH,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum UPLOAD_STRATEGY {
|
||||||
|
SINGLE_COLLECTION,
|
||||||
|
COLLECTION_PER_FOLDER,
|
||||||
|
}
|
||||||
|
|
||||||
export enum UPLOAD_RESULT {
|
export enum UPLOAD_RESULT {
|
||||||
FAILED,
|
FAILED,
|
||||||
ALREADY_UPLOADED,
|
ALREADY_UPLOADED,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { FILE_TYPE } from 'constants/file';
|
import { FILE_TYPE } from 'constants/file';
|
||||||
import { LIVE_PHOTO_ASSET_SIZE_LIMIT } from 'constants/upload';
|
import { LIVE_PHOTO_ASSET_SIZE_LIMIT } from 'constants/upload';
|
||||||
import { encodeMotionPhoto } from 'services/motionPhotoService';
|
import { encodeMotionPhoto } from 'services/motionPhotoService';
|
||||||
import { FileMagicMetadata } from 'types/file';
|
|
||||||
import {
|
import {
|
||||||
ElectronFile,
|
ElectronFile,
|
||||||
FileTypeInfo,
|
FileTypeInfo,
|
||||||
|
@ -62,12 +61,8 @@ export function getLivePhotoMetadata(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLivePhotoMagicMetadata(
|
export function getLivePhotoFilePath(imageAsset: Asset): string {
|
||||||
imageFile: FileWithCollection
|
return getLivePhotoName((imageAsset.file as any).path);
|
||||||
): FileMagicMetadata['data'] {
|
|
||||||
return {
|
|
||||||
filePaths: [getLivePhotoName((imageFile.file as any).path as string)],
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLivePhotoSize(livePhotoAssets: LivePhotoAssets) {
|
export function getLivePhotoSize(livePhotoAssets: LivePhotoAssets) {
|
||||||
|
@ -198,12 +193,11 @@ export function clusterLivePhotoFiles(mediaFiles: FileWithCollection[]) {
|
||||||
imageAsset.metadata,
|
imageAsset.metadata,
|
||||||
videoAsset.metadata
|
videoAsset.metadata
|
||||||
);
|
);
|
||||||
const livePhotoMagicMetadata: FileMagicMetadata['data'] =
|
const livePhotoPath = getLivePhotoFilePath(imageAsset);
|
||||||
getLivePhotoMagicMetadata(firstMediaFile);
|
|
||||||
uploadService.setFileMetadataAndFileTypeInfo(livePhotoLocalID, {
|
uploadService.setFileMetadataAndFileTypeInfo(livePhotoLocalID, {
|
||||||
fileTypeInfo: { ...livePhotoFileTypeInfo },
|
fileTypeInfo: { ...livePhotoFileTypeInfo },
|
||||||
metadata: { ...livePhotoMetadata },
|
metadata: { ...livePhotoMetadata },
|
||||||
magicMetadata: { ...livePhotoMagicMetadata },
|
filePath: livePhotoPath,
|
||||||
});
|
});
|
||||||
index += 2;
|
index += 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import { getLocalFiles, setLocalFiles } from '../fileService';
|
import {
|
||||||
|
getLocalFiles,
|
||||||
|
setLocalFiles,
|
||||||
|
updateFileMagicMetadata,
|
||||||
|
} from '../fileService';
|
||||||
import { SetFiles } from 'types/gallery';
|
import { SetFiles } from 'types/gallery';
|
||||||
import { getDedicatedCryptoWorker } from 'utils/crypto';
|
import { getDedicatedCryptoWorker } from 'utils/crypto';
|
||||||
import {
|
import {
|
||||||
|
@ -6,7 +10,7 @@ import {
|
||||||
sortFiles,
|
sortFiles,
|
||||||
preservePhotoswipeProps,
|
preservePhotoswipeProps,
|
||||||
decryptFile,
|
decryptFile,
|
||||||
changeFilePaths,
|
appendNewFilePath,
|
||||||
} from 'utils/file';
|
} from 'utils/file';
|
||||||
import { logError } from 'utils/sentry';
|
import { logError } from 'utils/sentry';
|
||||||
import { getMetadataJSONMapKey, parseMetadataJSON } from './metadataService';
|
import { getMetadataJSONMapKey, parseMetadataJSON } from './metadataService';
|
||||||
|
@ -20,7 +24,7 @@ import UIService from './uiService';
|
||||||
import UploadService from './uploadService';
|
import UploadService from './uploadService';
|
||||||
import { CustomError } from 'utils/error';
|
import { CustomError } from 'utils/error';
|
||||||
import { Collection } from 'types/collection';
|
import { Collection } from 'types/collection';
|
||||||
import { EnteFile, FileMagicMetadata } from 'types/file';
|
import { EnteFile } from 'types/file';
|
||||||
import {
|
import {
|
||||||
FileWithCollection,
|
FileWithCollection,
|
||||||
MetadataAndFileTypeInfo,
|
MetadataAndFileTypeInfo,
|
||||||
|
@ -230,7 +234,7 @@ class UploadManager {
|
||||||
UIService.reset(mediaFiles.length);
|
UIService.reset(mediaFiles.length);
|
||||||
for (const { file, localID, collectionID } of mediaFiles) {
|
for (const { file, localID, collectionID } of mediaFiles) {
|
||||||
try {
|
try {
|
||||||
const { fileTypeInfo, metadata, magicMetadata } =
|
const { fileTypeInfo, metadata, filePath } =
|
||||||
await (async () => {
|
await (async () => {
|
||||||
if (file.size >= MAX_FILE_SIZE_SUPPORTED) {
|
if (file.size >= MAX_FILE_SIZE_SUPPORTED) {
|
||||||
logUploadInfo(
|
logUploadInfo(
|
||||||
|
@ -260,10 +264,8 @@ class UploadManager {
|
||||||
collectionID,
|
collectionID,
|
||||||
fileTypeInfo
|
fileTypeInfo
|
||||||
)) || null;
|
)) || null;
|
||||||
const magicMetadata = {
|
const filePath = (file as any).path as string;
|
||||||
filePaths: [(file as any).path as string],
|
return { fileTypeInfo, metadata, filePath };
|
||||||
} as FileMagicMetadata['data'];
|
|
||||||
return { fileTypeInfo, metadata, magicMetadata };
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
logUploadInfo(
|
logUploadInfo(
|
||||||
|
@ -274,7 +276,7 @@ class UploadManager {
|
||||||
this.metadataAndFileTypeInfoMap.set(localID, {
|
this.metadataAndFileTypeInfoMap.set(localID, {
|
||||||
fileTypeInfo: fileTypeInfo && { ...fileTypeInfo },
|
fileTypeInfo: fileTypeInfo && { ...fileTypeInfo },
|
||||||
metadata: metadata && { ...metadata },
|
metadata: metadata && { ...metadata },
|
||||||
magicMetadata: magicMetadata && { ...magicMetadata },
|
filePath: filePath,
|
||||||
});
|
});
|
||||||
UIService.increaseFileUploaded();
|
UIService.increaseFileUploaded();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -340,25 +342,18 @@ class UploadManager {
|
||||||
this.existingFiles,
|
this.existingFiles,
|
||||||
fileWithCollection
|
fileWithCollection
|
||||||
);
|
);
|
||||||
const filePaths = UploadService.getFileMetadataAndFileTypeInfo(
|
|
||||||
fileWithCollection.localID
|
const finalUploadResult = await this.postUploadTask(
|
||||||
).magicMetadata.filePaths;
|
|
||||||
await changeFilePaths(
|
|
||||||
fileUploadResult,
|
|
||||||
uploadedFile,
|
|
||||||
fileWithCollection.collection.key,
|
|
||||||
filePaths
|
|
||||||
);
|
|
||||||
UIService.moveFileToResultList(
|
|
||||||
fileWithCollection.localID,
|
|
||||||
fileUploadResult
|
|
||||||
);
|
|
||||||
UploadService.reducePendingUploadCount();
|
|
||||||
await this.postUploadTask(
|
|
||||||
fileUploadResult,
|
fileUploadResult,
|
||||||
uploadedFile,
|
uploadedFile,
|
||||||
fileWithCollection
|
fileWithCollection
|
||||||
);
|
);
|
||||||
|
|
||||||
|
UIService.moveFileToResultList(
|
||||||
|
fileWithCollection.localID,
|
||||||
|
finalUploadResult
|
||||||
|
);
|
||||||
|
UploadService.reducePendingUploadCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +378,10 @@ class UploadManager {
|
||||||
uploadedFile
|
uploadedFile
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
await this.updateFilePaths(
|
||||||
|
uploadedFile,
|
||||||
|
fileWithCollection
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case UPLOAD_RESULT.ADDED_SYMLINK:
|
case UPLOAD_RESULT.ADDED_SYMLINK:
|
||||||
decryptedFile = uploadedFile;
|
decryptedFile = uploadedFile;
|
||||||
|
@ -404,14 +403,16 @@ class UploadManager {
|
||||||
fileWithCollection,
|
fileWithCollection,
|
||||||
uploadedFile
|
uploadedFile
|
||||||
);
|
);
|
||||||
|
await this.updateFilePaths(decryptedFile, fileWithCollection);
|
||||||
}
|
}
|
||||||
|
return fileUploadResult;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError(e, 'failed to do post file upload action');
|
logError(e, 'failed to do post file upload action');
|
||||||
logUploadInfo(
|
logUploadInfo(
|
||||||
`failed to do post file upload action -> ${e.message}
|
`failed to do post file upload action -> ${e.message}
|
||||||
${(e as Error).stack}`
|
${(e as Error).stack}`
|
||||||
);
|
);
|
||||||
throw e;
|
return UPLOAD_RESULT.FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,6 +458,18 @@ class UploadManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async updateFilePaths(
|
||||||
|
decryptedFile: EnteFile,
|
||||||
|
fileWithCollection: FileWithCollection
|
||||||
|
) {
|
||||||
|
const filePath = UploadService.getFileMetadataAndFileTypeInfo(
|
||||||
|
fileWithCollection.localID
|
||||||
|
).filePath;
|
||||||
|
|
||||||
|
const updatedFile = await appendNewFilePath(decryptedFile, filePath);
|
||||||
|
await updateFileMagicMetadata([updatedFile]);
|
||||||
|
}
|
||||||
|
|
||||||
async retryFailedFiles() {
|
async retryFailedFiles() {
|
||||||
await this.queueFilesForUpload(this.failedFiles, [
|
await this.queueFilesForUpload(this.failedFiles, [
|
||||||
...this.collections.values(),
|
...this.collections.values(),
|
||||||
|
|
|
@ -16,8 +16,8 @@ import {
|
||||||
diskFileRemovedCallback,
|
diskFileRemovedCallback,
|
||||||
diskFolderRemovedCallback,
|
diskFolderRemovedCallback,
|
||||||
} from './watchFolderEventHandlers';
|
} from './watchFolderEventHandlers';
|
||||||
import { UPLOAD_STRATEGY } from 'components/pages/gallery/Upload';
|
|
||||||
import { getParentFolderName } from './utils';
|
import { getParentFolderName } from './utils';
|
||||||
|
import { UPLOAD_STRATEGY } from 'constants/upload';
|
||||||
|
|
||||||
class watchFolderService {
|
class watchFolderService {
|
||||||
private ElectronAPIs: ElectronAPIsInterface;
|
private ElectronAPIs: ElectronAPIsInterface;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { FILE_TYPE } from 'constants/file';
|
import { FILE_TYPE } from 'constants/file';
|
||||||
import { Collection } from 'types/collection';
|
import { Collection } from 'types/collection';
|
||||||
import { fileAttribute, FileMagicMetadata } from 'types/file';
|
import { fileAttribute } from 'types/file';
|
||||||
|
|
||||||
export interface DataStream {
|
export interface DataStream {
|
||||||
stream: ReadableStream<Uint8Array>;
|
stream: ReadableStream<Uint8Array>;
|
||||||
|
@ -92,7 +92,7 @@ export interface FileWithCollection extends UploadAsset {
|
||||||
export interface MetadataAndFileTypeInfo {
|
export interface MetadataAndFileTypeInfo {
|
||||||
metadata: Metadata;
|
metadata: Metadata;
|
||||||
fileTypeInfo: FileTypeInfo;
|
fileTypeInfo: FileTypeInfo;
|
||||||
magicMetadata: FileMagicMetadata['data'];
|
filePath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MetadataAndFileTypeInfoMap = Map<number, MetadataAndFileTypeInfo>;
|
export type MetadataAndFileTypeInfoMap = Map<number, MetadataAndFileTypeInfo>;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { UPLOAD_STRATEGY } from 'components/pages/gallery/Upload';
|
import { UPLOAD_STRATEGY } from 'constants/upload';
|
||||||
import { ElectronFile } from 'types/upload';
|
import { ElectronFile } from 'types/upload';
|
||||||
|
|
||||||
export interface WatchMapping {
|
export interface WatchMapping {
|
||||||
|
|
|
@ -26,8 +26,7 @@ import ffmpegService from 'services/ffmpeg/ffmpegService';
|
||||||
import { NEW_FILE_MAGIC_METADATA, VISIBILITY_STATE } from 'types/magicMetadata';
|
import { NEW_FILE_MAGIC_METADATA, VISIBILITY_STATE } from 'types/magicMetadata';
|
||||||
import { IsArchived, updateMagicMetadataProps } from 'utils/magicMetadata';
|
import { IsArchived, updateMagicMetadataProps } from 'utils/magicMetadata';
|
||||||
import { ARCHIVE_SECTION, TRASH_SECTION } from 'constants/collection';
|
import { ARCHIVE_SECTION, TRASH_SECTION } from 'constants/collection';
|
||||||
import { UPLOAD_RESULT } from 'constants/upload';
|
|
||||||
import { updateFileMagicMetadata } from 'services/fileService';
|
|
||||||
export function downloadAsFile(filename: string, content: string) {
|
export function downloadAsFile(filename: string, content: string) {
|
||||||
const file = new Blob([content], {
|
const file = new Blob([content], {
|
||||||
type: 'text/plain',
|
type: 'text/plain',
|
||||||
|
@ -454,35 +453,24 @@ export async function changeFileName(file: EnteFile, editedName: string) {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const changeFilePaths = async (
|
export const appendNewFilePath = async (file: EnteFile, filePath: string) => {
|
||||||
fileUploadResult: UPLOAD_RESULT,
|
let mergedMetadataFilePaths = [filePath];
|
||||||
file: EnteFile,
|
if (file.magicMetadata?.data.filePaths?.length > 0) {
|
||||||
collectionKey: string,
|
mergedMetadataFilePaths = [
|
||||||
filePaths: string[]
|
...new Set([
|
||||||
) => {
|
...file.magicMetadata.data.filePaths,
|
||||||
if (
|
...mergedMetadataFilePaths,
|
||||||
fileUploadResult === UPLOAD_RESULT.UPLOADED ||
|
]),
|
||||||
fileUploadResult === UPLOAD_RESULT.ALREADY_UPLOADED ||
|
];
|
||||||
fileUploadResult === UPLOAD_RESULT.UPLOADED_WITH_STATIC_THUMBNAIL
|
|
||||||
) {
|
|
||||||
let mergedMetadataFilePaths = [...filePaths];
|
|
||||||
if (file.magicMetadata?.data.filePaths?.length > 0) {
|
|
||||||
mergedMetadataFilePaths = [
|
|
||||||
...new Set([
|
|
||||||
...file.magicMetadata.data.filePaths,
|
|
||||||
...filePaths,
|
|
||||||
]),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
file.key = await getFileKey(file, collectionKey);
|
|
||||||
const updatedMagicMetadata = await updateMagicMetadataProps(
|
|
||||||
file.magicMetadata ?? NEW_FILE_MAGIC_METADATA,
|
|
||||||
file.key,
|
|
||||||
{ filePaths: mergedMetadataFilePaths }
|
|
||||||
);
|
|
||||||
file.magicMetadata = updatedMagicMetadata;
|
|
||||||
await updateFileMagicMetadata([file]);
|
|
||||||
}
|
}
|
||||||
|
const updatedMagicMetadata = await updateMagicMetadataProps(
|
||||||
|
file.magicMetadata ?? NEW_FILE_MAGIC_METADATA,
|
||||||
|
file.key,
|
||||||
|
{ filePaths: mergedMetadataFilePaths }
|
||||||
|
);
|
||||||
|
file.magicMetadata = updatedMagicMetadata;
|
||||||
|
|
||||||
|
return file;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function isSharedFile(file: EnteFile) {
|
export function isSharedFile(file: EnteFile) {
|
||||||
|
|
Loading…
Reference in a new issue