Retain more info

Also invent a new scheme for passing around this data instead of piggy backing
on the JSON route, since the JSON route has other complications (e.g. it strips
off the "-edited" prefix) that we'd anyways would've needed to workaround.
This commit is contained in:
Manav Rathi
2024-11-15 10:21:12 +05:30
parent 708109f5e4
commit 057bd3a4d2
4 changed files with 61 additions and 28 deletions

View File

@@ -478,11 +478,7 @@ const ImageEditorOverlay = (props: IProps) => {
uploadManager.prepareForNewUpload();
uploadManager.showUploadProgressDialog();
uploadManager.uploadFile(
editedFile,
collection,
props.file.metadata.creationTime,
);
uploadManager.uploadFile(editedFile, collection, props.file);
setFileURL(null);
props.onClose();
props.closePhotoViewer();

View File

@@ -197,10 +197,25 @@ export const uploadItemFileName = (uploadItem: UploadItem) => {
/* -- Various intermediate type used during upload -- */
interface UploadAsset {
export interface UploadAsset {
/** `true` if this is a live photo. */
isLivePhoto?: boolean;
uploadItem?: UploadItem;
/* Valid for live photos */
livePhotoAssets?: LivePhotoAssets;
/* Valid for non-live photos */
uploadItem?: UploadItem;
/**
* Metadata we know about a file externally. Valid for non-live photos.
*
* This is metadata that is not present within the file, but we have
* available from external sources. There is also a parsed metadata we
* obtain from JSON files. So together with the metadata present within the
* file itself, there are three places where the file's initial metadata can
* be filled in from.
*
* This will not be present for live photos.
*/
externalParsedMetadata?: ParsedMetadata;
}
interface ThumbnailedFile {
@@ -871,7 +886,12 @@ interface ExtractAssetMetadataResult {
* {@link parsedMetadataJSONMap} for the assets. Return the resultant metadatum.
*/
const extractAssetMetadata = async (
{ isLivePhoto, uploadItem, livePhotoAssets }: UploadAsset,
{
isLivePhoto,
uploadItem,
externalParsedMetadata,
livePhotoAssets,
}: UploadAsset,
fileTypeInfo: FileTypeInfo,
lastModifiedMs: number,
collectionID: number,
@@ -889,6 +909,7 @@ const extractAssetMetadata = async (
)
: await extractImageOrVideoMetadata(
uploadItem,
externalParsedMetadata,
fileTypeInfo,
lastModifiedMs,
collectionID,
@@ -911,6 +932,7 @@ const extractLivePhotoMetadata = async (
const { metadata: imageMetadata, publicMagicMetadata } =
await extractImageOrVideoMetadata(
livePhotoAssets.image,
undefined,
imageFileTypeInfo,
lastModifiedMs,
collectionID,
@@ -935,6 +957,7 @@ const extractLivePhotoMetadata = async (
const extractImageOrVideoMetadata = async (
uploadItem: UploadItem,
externalParsedMetadata: ParsedMetadata | undefined,
fileTypeInfo: FileTypeInfo,
lastModifiedMs: number,
collectionID: number,
@@ -956,6 +979,12 @@ const extractImageOrVideoMetadata = async (
throw new Error(`Unexpected file type ${fileType} for ${uploadItem}`);
}
// The `UploadAsset` itself might have metadata associated with a-priori, if
// so, merge the data we read from the file's contents into it.
if (externalParsedMetadata) {
parsedMetadata = { ...externalParsedMetadata, ...parsedMetadata };
}
const hash = await computeHash(uploadItem, worker);
// Some of this logic is duplicated in `uploadItemCreationDate`.

View File

@@ -7,6 +7,7 @@ import { ComlinkWorker } from "@/base/worker/comlink-worker";
import { shouldDisableCFUploadProxy } from "@/gallery/upload";
import type { Collection } from "@/media/collection";
import { EncryptedEnteFile, EnteFile } from "@/media/file";
import type { ParsedMetadata } from "@/media/file-metadata";
import { FileType } from "@/media/file-type";
import { potentialFileTypeFromExtension } from "@/media/live-photo";
import { getLocalFiles } from "@/new/photos/services/files";
@@ -38,6 +39,7 @@ import UploadService, {
uploadItemFileName,
uploader,
type PotentialLivePhotoAsset,
type UploadAsset,
} from "./upload-service";
export type FileID = number;
@@ -85,13 +87,10 @@ export interface ProgressUpdater {
/** The number of uploads to process in parallel. */
const maxConcurrentUploads = 4;
export interface UploadItemWithCollection {
export type UploadItemWithCollection = UploadAsset & {
localID: number;
collectionID: number;
isLivePhoto?: boolean;
uploadItem?: UploadItem;
livePhotoAssets?: LivePhotoAssets;
}
};
export interface LivePhotoAssets {
image: UploadItem;
@@ -455,25 +454,35 @@ class UploadManager {
*
* @param file A web {@link File} object representing the file to upload.
*
* @param collection The {@link Collection} in which the file should be added.
* @param collection The {@link Collection} in which the file should be
* added.
*
* @param creationTime The timestamp (unix epoch microseconds) to use as the
* `creationTime` of the newly created {@link EnteFile}.
* @param sourceEnteFile The {@link EnteFile} from which the file being
* uploaded has been derived. This is used to extract and reassociated
* relevant metadata to the newly uploaded file.
*/
public async uploadFile(
file: File,
collection: Collection,
creationTime: number,
sourceEnteFile: EnteFile,
) {
const timestamp = sourceEnteFile.metadata.creationTime;
const dateTime = sourceEnteFile.pubMagicMetadata.data.dateTime;
const offset = sourceEnteFile.pubMagicMetadata.data.offsetTime;
const creationDate: ParsedMetadata["creationDate"] = {
timestamp,
dateTime,
offset,
};
const item = {
uploadItem: file,
localID: 1,
collectionID: collection.id,
externalParsedMetadata: { creationDate },
};
this.parsedMetadataJSONMap.set(
getMetadataJSONMapKeyForJSON(collection.id, file.name),
{ creationTime },
);
return this.uploadItems([item], [collection]);
}
@@ -732,7 +741,7 @@ export default new UploadManager();
* {@link collection}, giving us {@link UploadableUploadItem}. This is what
* gets queued and then passed to the {@link uploader}.
*/
type UploadItemWithCollectionIDAndName = {
type UploadItemWithCollectionIDAndName = UploadAsset & {
/** A unique ID for the duration of the upload */
localID: number;
/** The ID of the collection to which this file should be uploaded. */
@@ -743,12 +752,6 @@ type UploadItemWithCollectionIDAndName = {
* In case of live photos, this'll be the name of the image part.
*/
fileName: string;
/** `true` if this is a live photo. */
isLivePhoto?: boolean;
/* Valid for non-live photos */
uploadItem?: UploadItem;
/* Valid for live photos */
livePhotoAssets?: LivePhotoAssets;
};
const makeUploadItemWithCollectionIDAndName = (
@@ -764,6 +767,7 @@ const makeUploadItemWithCollectionIDAndName = (
isLivePhoto: f.isLivePhoto,
uploadItem: f.uploadItem,
livePhotoAssets: f.livePhotoAssets,
externalParsedMetadata: f.externalParsedMetadata,
});
/**

View File

@@ -163,6 +163,10 @@ export interface FilePublicMagicMetadataProps {
* Epoch microseconds.
*/
editedTime?: number;
/** See {@link PublicMagicMetadata} in file-metadata.ts */
dateTime?: string;
/** See {@link PublicMagicMetadata} in file-metadata.ts */
offsetTime?: string;
/**
* Edited name of the {@link EnteFile}.
*