Inner types
This commit is contained in:
parent
a7f5061eb6
commit
879f3389d1
|
@ -3,7 +3,7 @@ import { CustomError, handleUploadError } from "@ente/shared/error";
|
||||||
import HTTPService from "@ente/shared/network/HTTPService";
|
import HTTPService from "@ente/shared/network/HTTPService";
|
||||||
import { getEndpoint } from "@ente/shared/network/api";
|
import { getEndpoint } from "@ente/shared/network/api";
|
||||||
import { EnteFile } from "types/file";
|
import { EnteFile } from "types/file";
|
||||||
import { MultipartUploadURLs, UploadFile, UploadURL } from "types/upload";
|
import { MultipartUploadURLs, UploadFile, UploadURL } from "./uploadService";
|
||||||
import { retryHTTPCall } from "utils/upload/uploadRetrier";
|
import { retryHTTPCall } from "utils/upload/uploadRetrier";
|
||||||
|
|
||||||
const ENDPOINT = getEndpoint();
|
const ENDPOINT = getEndpoint();
|
||||||
|
|
|
@ -4,8 +4,8 @@ import HTTPService from "@ente/shared/network/HTTPService";
|
||||||
import { getEndpoint, getUploadEndpoint } from "@ente/shared/network/api";
|
import { getEndpoint, getUploadEndpoint } from "@ente/shared/network/api";
|
||||||
import { getToken } from "@ente/shared/storage/localStorage/helpers";
|
import { getToken } from "@ente/shared/storage/localStorage/helpers";
|
||||||
import { EnteFile } from "types/file";
|
import { EnteFile } from "types/file";
|
||||||
import { MultipartUploadURLs, UploadFile, UploadURL } from "types/upload";
|
|
||||||
import { retryHTTPCall } from "utils/upload/uploadRetrier";
|
import { retryHTTPCall } from "utils/upload/uploadRetrier";
|
||||||
|
import { MultipartUploadURLs, UploadFile, UploadURL } from "./uploadService";
|
||||||
|
|
||||||
const ENDPOINT = getEndpoint();
|
const ENDPOINT = getEndpoint();
|
||||||
const UPLOAD_ENDPOINT = getUploadEndpoint();
|
const UPLOAD_ENDPOINT = getUploadEndpoint();
|
||||||
|
|
|
@ -47,12 +47,7 @@ import {
|
||||||
tryParseTakeoutMetadataJSON,
|
tryParseTakeoutMetadataJSON,
|
||||||
type ParsedMetadataJSON,
|
type ParsedMetadataJSON,
|
||||||
} from "./takeout";
|
} from "./takeout";
|
||||||
import UploadService, {
|
import UploadService, { fopSize, getFileName, uploader } from "./uploadService";
|
||||||
assetName,
|
|
||||||
fopSize,
|
|
||||||
getFileName,
|
|
||||||
uploader,
|
|
||||||
} from "./uploadService";
|
|
||||||
|
|
||||||
/** The number of uploads to process in parallel. */
|
/** The number of uploads to process in parallel. */
|
||||||
const maxConcurrentUploads = 4;
|
const maxConcurrentUploads = 4;
|
||||||
|
@ -837,24 +832,17 @@ const clusterLivePhotos = async (files: FileWithCollectionIDAndName[]) => {
|
||||||
fileOrPath: g.fileOrPath,
|
fileOrPath: g.fileOrPath,
|
||||||
};
|
};
|
||||||
if (await areLivePhotoAssets(fa, ga)) {
|
if (await areLivePhotoAssets(fa, ga)) {
|
||||||
const livePhoto = {
|
const [image, video] =
|
||||||
|
fFileType == FILE_TYPE.IMAGE ? [f, g] : [g, f];
|
||||||
|
result.push({
|
||||||
localID: f.localID,
|
localID: f.localID,
|
||||||
collectionID: f.collectionID,
|
collectionID: f.collectionID,
|
||||||
|
fileName: image.fileName,
|
||||||
isLivePhoto: true,
|
isLivePhoto: true,
|
||||||
livePhotoAssets: {
|
livePhotoAssets: {
|
||||||
image:
|
image: image.fileOrPath,
|
||||||
fFileType == FILE_TYPE.IMAGE
|
video: video.fileOrPath,
|
||||||
? f.fileOrPath
|
|
||||||
: g.fileOrPath,
|
|
||||||
video:
|
|
||||||
fFileType == FILE_TYPE.IMAGE
|
|
||||||
? g.fileOrPath
|
|
||||||
: f.fileOrPath,
|
|
||||||
},
|
},
|
||||||
};
|
|
||||||
result.push({
|
|
||||||
...livePhoto,
|
|
||||||
fileName: assetName(livePhoto),
|
|
||||||
});
|
});
|
||||||
index += 2;
|
index += 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -8,7 +8,11 @@ import { ElectronFile } from "@/next/types/file";
|
||||||
import { CustomErrorMessage } from "@/next/types/ipc";
|
import { CustomErrorMessage } from "@/next/types/ipc";
|
||||||
import { ensure } from "@/utils/ensure";
|
import { ensure } from "@/utils/ensure";
|
||||||
import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker";
|
import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker";
|
||||||
import { EncryptionResult } from "@ente/shared/crypto/types";
|
import {
|
||||||
|
B64EncryptionResult,
|
||||||
|
EncryptionResult,
|
||||||
|
LocalFileAttributes,
|
||||||
|
} from "@ente/shared/crypto/types";
|
||||||
import { CustomError, handleUploadError } from "@ente/shared/error";
|
import { CustomError, handleUploadError } from "@ente/shared/error";
|
||||||
import { isDataStream, type DataStream } from "@ente/shared/utils/data-stream";
|
import { isDataStream, type DataStream } from "@ente/shared/utils/data-stream";
|
||||||
import { Remote } from "comlink";
|
import { Remote } from "comlink";
|
||||||
|
@ -25,24 +29,18 @@ import { parseImageMetadata } from "services/exif";
|
||||||
import * as ffmpeg from "services/ffmpeg";
|
import * as ffmpeg from "services/ffmpeg";
|
||||||
import {
|
import {
|
||||||
EnteFile,
|
EnteFile,
|
||||||
|
MetadataFileAttributes,
|
||||||
|
S3FileAttributes,
|
||||||
type EncryptedEnteFile,
|
type EncryptedEnteFile,
|
||||||
type FilePublicMagicMetadata,
|
type FilePublicMagicMetadata,
|
||||||
type FilePublicMagicMetadataProps,
|
type FilePublicMagicMetadataProps,
|
||||||
} from "types/file";
|
} from "types/file";
|
||||||
import { EncryptedMagicMetadata } from "types/magicMetadata";
|
import { EncryptedMagicMetadata } from "types/magicMetadata";
|
||||||
import {
|
import {
|
||||||
BackupedFile,
|
|
||||||
EncryptedFile,
|
|
||||||
FileInMemory,
|
|
||||||
FileWithMetadata,
|
|
||||||
ParsedExtractedMetadata,
|
ParsedExtractedMetadata,
|
||||||
ProcessedFile,
|
|
||||||
PublicUploadProps,
|
PublicUploadProps,
|
||||||
UploadAsset,
|
UploadAsset,
|
||||||
UploadFile,
|
|
||||||
UploadURL,
|
|
||||||
type LivePhotoAssets2,
|
type LivePhotoAssets2,
|
||||||
type UploadAsset2,
|
|
||||||
} from "types/upload";
|
} from "types/upload";
|
||||||
import {
|
import {
|
||||||
getNonEmptyMagicMetadataProps,
|
getNonEmptyMagicMetadataProps,
|
||||||
|
@ -147,6 +145,68 @@ const uploadService = new UploadService();
|
||||||
|
|
||||||
export default uploadService;
|
export default uploadService;
|
||||||
|
|
||||||
|
/* -- Various intermediate type used during upload -- */
|
||||||
|
|
||||||
|
interface UploadAsset2 {
|
||||||
|
isLivePhoto?: boolean;
|
||||||
|
fileOrPath?: File | string;
|
||||||
|
livePhotoAssets?: LivePhotoAssets2;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FileInMemory {
|
||||||
|
filedata: Uint8Array | DataStream;
|
||||||
|
/** The JPEG data of the generated thumbnail */
|
||||||
|
thumbnail: Uint8Array;
|
||||||
|
/**
|
||||||
|
* `true` if this is a fallback (all black) thumbnail we're returning since
|
||||||
|
* thumbnail generation failed for some reason.
|
||||||
|
*/
|
||||||
|
hasStaticThumbnail: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FileWithMetadata extends Omit<FileInMemory, "hasStaticThumbnail"> {
|
||||||
|
metadata: Metadata;
|
||||||
|
localID: number;
|
||||||
|
pubMagicMetadata: FilePublicMagicMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface EncryptedFile {
|
||||||
|
file: ProcessedFile;
|
||||||
|
fileKey: B64EncryptionResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ProcessedFile {
|
||||||
|
file: LocalFileAttributes<Uint8Array | DataStream>;
|
||||||
|
thumbnail: LocalFileAttributes<Uint8Array>;
|
||||||
|
metadata: LocalFileAttributes<string>;
|
||||||
|
pubMagicMetadata: EncryptedMagicMetadata;
|
||||||
|
localID: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BackupedFile {
|
||||||
|
file: S3FileAttributes;
|
||||||
|
thumbnail: S3FileAttributes;
|
||||||
|
metadata: MetadataFileAttributes;
|
||||||
|
pubMagicMetadata: EncryptedMagicMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UploadFile extends BackupedFile {
|
||||||
|
collectionID: number;
|
||||||
|
encryptedKey: string;
|
||||||
|
keyDecryptionNonce: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MultipartUploadURLs {
|
||||||
|
objectKey: string;
|
||||||
|
partURLs: string[];
|
||||||
|
completeURL: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UploadURL {
|
||||||
|
url: string;
|
||||||
|
objectKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function that can be called to obtain a "progressTracker" that then is
|
* A function that can be called to obtain a "progressTracker" that then is
|
||||||
* directly fed to axios to both cancel the upload if needed, and update the
|
* directly fed to axios to both cancel the upload if needed, and update the
|
||||||
|
@ -165,8 +225,15 @@ interface UploadResponse {
|
||||||
uploadedFile?: EncryptedEnteFile | EnteFile;
|
uploadedFile?: EncryptedEnteFile | EnteFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload the given {@link UploadableFile}
|
||||||
|
*
|
||||||
|
* This is lower layer implementation of the upload. It is invoked by
|
||||||
|
* {@link UploadManager} after it has assembled all the relevant bits we need to
|
||||||
|
* go forth and upload.
|
||||||
|
*/
|
||||||
export const uploader = async (
|
export const uploader = async (
|
||||||
fileWithCollection: UploadableFile,
|
{ collection, localID, fileName, ...uploadAsset }: UploadableFile,
|
||||||
uploaderName: string,
|
uploaderName: string,
|
||||||
existingFiles: EnteFile[],
|
existingFiles: EnteFile[],
|
||||||
parsedMetadataJSONMap: Map<string, ParsedMetadataJSON>,
|
parsedMetadataJSONMap: Map<string, ParsedMetadataJSON>,
|
||||||
|
@ -175,10 +242,7 @@ export const uploader = async (
|
||||||
abortIfCancelled: () => void,
|
abortIfCancelled: () => void,
|
||||||
makeProgessTracker: MakeProgressTracker,
|
makeProgessTracker: MakeProgressTracker,
|
||||||
): Promise<UploadResponse> => {
|
): Promise<UploadResponse> => {
|
||||||
const { collection, localID, ...uploadAsset } = fileWithCollection;
|
log.info(`Uploading ${fileName}`);
|
||||||
const name = assetName(uploadAsset);
|
|
||||||
log.info(`Uploading ${name}`);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
/*
|
/*
|
||||||
* We read the file four times:
|
* We read the file four times:
|
||||||
|
@ -295,11 +359,11 @@ export const uploader = async (
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.message == CustomError.UPLOAD_CANCELLED) {
|
if (e.message == CustomError.UPLOAD_CANCELLED) {
|
||||||
log.info(`Upload for ${name} cancelled`);
|
log.info(`Upload for ${fileName} cancelled`);
|
||||||
} else if (e.message == CustomError.UNSUPPORTED_FILE_FORMAT) {
|
} else if (e.message == CustomError.UNSUPPORTED_FILE_FORMAT) {
|
||||||
log.info(`Not uploading ${name}: unsupported file format`);
|
log.info(`Not uploading ${fileName}: unsupported file format`);
|
||||||
} else {
|
} else {
|
||||||
log.error(`Upload failed for ${name}`, e);
|
log.error(`Upload failed for ${fileName}`, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
const error = handleUploadError(e);
|
const error = handleUploadError(e);
|
||||||
|
@ -339,13 +403,6 @@ export const getAssetName = ({
|
||||||
}: UploadAsset) =>
|
}: UploadAsset) =>
|
||||||
isLivePhoto ? getFileName(livePhotoAssets.image) : getFileName(file);
|
isLivePhoto ? getFileName(livePhotoAssets.image) : getFileName(file);
|
||||||
|
|
||||||
export const assetName = ({
|
|
||||||
isLivePhoto,
|
|
||||||
file,
|
|
||||||
livePhotoAssets,
|
|
||||||
}: UploadAsset2) =>
|
|
||||||
isLivePhoto ? getFileName(livePhotoAssets.image) : getFileName(file);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the given file or path into an in-memory representation.
|
* Read the given file or path into an in-memory representation.
|
||||||
*
|
*
|
||||||
|
@ -462,11 +519,11 @@ interface ReadAssetDetailsResult {
|
||||||
const readAssetDetails = async ({
|
const readAssetDetails = async ({
|
||||||
isLivePhoto,
|
isLivePhoto,
|
||||||
livePhotoAssets,
|
livePhotoAssets,
|
||||||
file,
|
fileOrPath,
|
||||||
}: UploadAsset2): Promise<ReadAssetDetailsResult> =>
|
}: UploadAsset2): Promise<ReadAssetDetailsResult> =>
|
||||||
isLivePhoto
|
isLivePhoto
|
||||||
? readLivePhotoDetails(livePhotoAssets)
|
? readLivePhotoDetails(livePhotoAssets)
|
||||||
: readImageOrVideoDetails(file);
|
: readImageOrVideoDetails(fileOrPath);
|
||||||
|
|
||||||
const readLivePhotoDetails = async ({ image, video }: LivePhotoAssets2) => {
|
const readLivePhotoDetails = async ({ image, video }: LivePhotoAssets2) => {
|
||||||
const img = await readImageOrVideoDetails(image);
|
const img = await readImageOrVideoDetails(image);
|
||||||
|
@ -533,7 +590,7 @@ interface ExtractAssetMetadataResult {
|
||||||
* {@link parsedMetadataJSONMap} for the assets. Return the resultant metadatum.
|
* {@link parsedMetadataJSONMap} for the assets. Return the resultant metadatum.
|
||||||
*/
|
*/
|
||||||
const extractAssetMetadata = async (
|
const extractAssetMetadata = async (
|
||||||
{ isLivePhoto, file, livePhotoAssets }: UploadAsset2,
|
{ isLivePhoto, fileOrPath, livePhotoAssets }: UploadAsset2,
|
||||||
fileTypeInfo: FileTypeInfo,
|
fileTypeInfo: FileTypeInfo,
|
||||||
lastModifiedMs: number,
|
lastModifiedMs: number,
|
||||||
collectionID: number,
|
collectionID: number,
|
||||||
|
@ -550,7 +607,7 @@ const extractAssetMetadata = async (
|
||||||
worker,
|
worker,
|
||||||
)
|
)
|
||||||
: await extractImageOrVideoMetadata(
|
: await extractImageOrVideoMetadata(
|
||||||
file,
|
fileOrPath,
|
||||||
fileTypeInfo,
|
fileTypeInfo,
|
||||||
lastModifiedMs,
|
lastModifiedMs,
|
||||||
collectionID,
|
collectionID,
|
||||||
|
@ -774,11 +831,11 @@ const areFilesSameNoHash = (f: Metadata, g: Metadata) => {
|
||||||
|
|
||||||
const readAsset = async (
|
const readAsset = async (
|
||||||
fileTypeInfo: FileTypeInfo,
|
fileTypeInfo: FileTypeInfo,
|
||||||
{ isLivePhoto, file, livePhotoAssets }: UploadAsset2,
|
{ isLivePhoto, fileOrPath, livePhotoAssets }: UploadAsset2,
|
||||||
) =>
|
) =>
|
||||||
isLivePhoto
|
isLivePhoto
|
||||||
? await readLivePhoto(livePhotoAssets, fileTypeInfo)
|
? await readLivePhoto(livePhotoAssets, fileTypeInfo)
|
||||||
: await readImageOrVideo(file, fileTypeInfo);
|
: await readImageOrVideo(fileOrPath, fileTypeInfo);
|
||||||
|
|
||||||
const readLivePhoto = async (
|
const readLivePhoto = async (
|
||||||
livePhotoAssets: LivePhotoAssets2,
|
livePhotoAssets: LivePhotoAssets2,
|
||||||
|
|
|
@ -1,29 +1,11 @@
|
||||||
import type { Metadata } from "@/media/types/file";
|
|
||||||
import type { ElectronFile } from "@/next/types/file";
|
import type { ElectronFile } from "@/next/types/file";
|
||||||
import {
|
|
||||||
B64EncryptionResult,
|
|
||||||
LocalFileAttributes,
|
|
||||||
} from "@ente/shared/crypto/types";
|
|
||||||
import type { DataStream } from "@ente/shared/utils/data-stream";
|
|
||||||
import { Collection } from "types/collection";
|
import { Collection } from "types/collection";
|
||||||
import {
|
|
||||||
FilePublicMagicMetadata,
|
|
||||||
MetadataFileAttributes,
|
|
||||||
S3FileAttributes,
|
|
||||||
} from "types/file";
|
|
||||||
import { EncryptedMagicMetadata } from "types/magicMetadata";
|
|
||||||
|
|
||||||
export interface Location {
|
export interface Location {
|
||||||
latitude: number;
|
latitude: number;
|
||||||
longitude: number;
|
longitude: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MultipartUploadURLs {
|
|
||||||
objectKey: string;
|
|
||||||
partURLs: string[];
|
|
||||||
completeURL: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UploadAsset {
|
export interface UploadAsset {
|
||||||
isLivePhoto?: boolean;
|
isLivePhoto?: boolean;
|
||||||
file?: File | ElectronFile;
|
file?: File | ElectronFile;
|
||||||
|
@ -42,72 +24,17 @@ export interface FileWithCollection extends UploadAsset {
|
||||||
collectionID?: number;
|
collectionID?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UploadAsset2 {
|
|
||||||
isLivePhoto?: boolean;
|
|
||||||
file?: File | string;
|
|
||||||
fileOrPath?: File | string;
|
|
||||||
livePhotoAssets?: LivePhotoAssets2;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LivePhotoAssets2 {
|
export interface LivePhotoAssets2 {
|
||||||
image: File | string;
|
image: File | string;
|
||||||
video: File | string;
|
video: File | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileWithCollection2 extends UploadAsset2 {
|
export interface FileWithCollection2 extends UploadAsset {
|
||||||
localID: number;
|
localID: number;
|
||||||
collection?: Collection;
|
collection?: Collection;
|
||||||
collectionID: number;
|
collectionID: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UploadURL {
|
|
||||||
url: string;
|
|
||||||
objectKey: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileInMemory {
|
|
||||||
filedata: Uint8Array | DataStream;
|
|
||||||
/** The JPEG data of the generated thumbnail */
|
|
||||||
thumbnail: Uint8Array;
|
|
||||||
/**
|
|
||||||
* `true` if this is a fallback (all black) thumbnail we're returning since
|
|
||||||
* thumbnail generation failed for some reason.
|
|
||||||
*/
|
|
||||||
hasStaticThumbnail: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface FileWithMetadata
|
|
||||||
extends Omit<FileInMemory, "hasStaticThumbnail"> {
|
|
||||||
metadata: Metadata;
|
|
||||||
localID: number;
|
|
||||||
pubMagicMetadata: FilePublicMagicMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface EncryptedFile {
|
|
||||||
file: ProcessedFile;
|
|
||||||
fileKey: B64EncryptionResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProcessedFile {
|
|
||||||
file: LocalFileAttributes<Uint8Array | DataStream>;
|
|
||||||
thumbnail: LocalFileAttributes<Uint8Array>;
|
|
||||||
metadata: LocalFileAttributes<string>;
|
|
||||||
pubMagicMetadata: EncryptedMagicMetadata;
|
|
||||||
localID: number;
|
|
||||||
}
|
|
||||||
export interface BackupedFile {
|
|
||||||
file: S3FileAttributes;
|
|
||||||
thumbnail: S3FileAttributes;
|
|
||||||
metadata: MetadataFileAttributes;
|
|
||||||
pubMagicMetadata: EncryptedMagicMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UploadFile extends BackupedFile {
|
|
||||||
collectionID: number;
|
|
||||||
encryptedKey: string;
|
|
||||||
keyDecryptionNonce: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ParsedExtractedMetadata {
|
export interface ParsedExtractedMetadata {
|
||||||
location: Location;
|
location: Location;
|
||||||
creationTime: number;
|
creationTime: number;
|
||||||
|
|
Loading…
Reference in a new issue