diff --git a/web/apps/photos/src/services/publicCollectionService.ts b/web/apps/photos/src/services/publicCollectionService.ts index 870c1c887b..1a9d598a68 100644 --- a/web/apps/photos/src/services/publicCollectionService.ts +++ b/web/apps/photos/src/services/publicCollectionService.ts @@ -1,15 +1,12 @@ import { sharedCryptoWorker } from "ente-base/crypto"; import log from "ente-base/log"; import { apiURL } from "ente-base/origins"; +import { type MagicMetadataCore } from "ente-gallery/services/magic-metadata"; import type { Collection, CollectionPublicMagicMetadataData, } from "ente-media/collection"; -import type { - EnteFile, - MagicMetadataCore, - RemoteEnteFile, -} from "ente-media/file"; +import type { EnteFile, RemoteEnteFile } from "ente-media/file"; import { decryptRemoteFile, mergeMetadata } from "ente-media/file"; import { savedPublicCollections } from "ente-new/albums/services/public-albums-fdb"; import { sortFiles } from "ente-new/photos/services/files"; diff --git a/web/packages/gallery/services/magic-metadata.ts b/web/packages/gallery/services/magic-metadata.ts index fc3998351c..de0b536fc5 100644 --- a/web/packages/gallery/services/magic-metadata.ts +++ b/web/packages/gallery/services/magic-metadata.ts @@ -3,9 +3,15 @@ /* eslint-disable @typescript-eslint/no-unnecessary-condition */ import { sharedCryptoWorker } from "ente-base/crypto"; import type { Collection } from "ente-media/collection"; -import { type MagicMetadataCore } from "ente-media/file"; import { ItemVisibility } from "ente-media/file-metadata"; +export interface MagicMetadataCore { + version: number; + count: number; + header: string; + data: T; +} + export const isArchivedCollection = (item: Collection) => { if (!item) { return false; diff --git a/web/packages/gallery/services/upload/remote.ts b/web/packages/gallery/services/upload/remote.ts index 165e5cb77d..b402bdc43a 100644 --- a/web/packages/gallery/services/upload/remote.ts +++ b/web/packages/gallery/services/upload/remote.ts @@ -7,11 +7,8 @@ import { type PublicAlbumsCredentials, } from "ente-base/http"; import { apiURL, uploaderOrigin } from "ente-base/origins"; -import { - type EncryptedMagicMetadata, - type RemoteEnteFile, - type RemoteFileMetadata, -} from "ente-media/file"; +import { type RemoteEnteFile, type RemoteFileMetadata } from "ente-media/file"; +import type { RemoteMagicMetadata } from "ente-media/magic-metadata"; import { nullToUndefined } from "ente-utils/transform"; import { z } from "zod/v4"; @@ -411,7 +408,7 @@ export interface PostEnteFileRequest { file: UploadedFileObjectAttributes; thumbnail: UploadedFileObjectAttributes; metadata: RemoteFileMetadata; - pubMagicMetadata: EncryptedMagicMetadata; + pubMagicMetadata?: RemoteMagicMetadata; } /** diff --git a/web/packages/gallery/services/upload/upload-service.ts b/web/packages/gallery/services/upload/upload-service.ts index 5fb597d787..04ba1a22b4 100644 --- a/web/packages/gallery/services/upload/upload-service.ts +++ b/web/packages/gallery/services/upload/upload-service.ts @@ -19,21 +19,12 @@ import { determineVideoDuration, extractVideoMetadata, } from "ente-gallery/services/ffmpeg"; -import { - getNonEmptyMagicMetadataProps, - updateMagicMetadata, -} from "ente-gallery/services/magic-metadata"; import { detectFileTypeInfoFromChunk, isFileTypeNotSupportedError, } from "ente-gallery/utils/detect-type"; import { readStream } from "ente-gallery/utils/native-stream"; -import type { - EncryptedMagicMetadata, - EnteFile, - FilePublicMagicMetadata, - RemoteEnteFile, -} from "ente-media/file"; +import type { EnteFile, RemoteEnteFile } from "ente-media/file"; import { fileFileName, metadataHash, @@ -43,6 +34,11 @@ import { } from "ente-media/file-metadata"; import { FileType, type FileTypeInfo } from "ente-media/file-type"; import { encodeLivePhoto } from "ente-media/live-photo"; +import { + createMagicMetadata, + encryptMagicMetadata, + type RemoteMagicMetadata, +} from "ente-media/magic-metadata"; import { addToCollection } from "ente-new/photos/services/collection"; import { mergeUint8Arrays } from "ente-utils/array"; import { ensureInteger, ensureNumber } from "ente-utils/ensure"; @@ -279,9 +275,9 @@ interface ThumbnailedFile { } interface FileWithMetadata extends Omit { - metadata: FileMetadata; localID: number; - pubMagicMetadata: FilePublicMagicMetadata; + metadata: FileMetadata; + publicMagicMetadata: FilePublicMagicMetadataData; } interface EncryptedFileStream { @@ -320,7 +316,7 @@ interface EncryptedFilePieces { * the decryption header that was used during encryption (base64 string). */ metadata: { encryptedData: string; decryptionHeader: string }; - pubMagicMetadata: EncryptedMagicMetadata; + pubMagicMetadata: RemoteMagicMetadata | undefined; localID: number; } @@ -741,11 +737,6 @@ export const upload = async ( if (hasStaticThumbnail) metadata.hasStaticThumbnail = true; - const pubMagicMetadata = await constructPublicMagicMetadata({ - ...publicMagicMetadata, - uploaderName, - }); - abortIfCancelled(); const fileWithMetadata: FileWithMetadata = { @@ -753,7 +744,10 @@ export const upload = async ( fileStreamOrData, thumbnail, metadata, - pubMagicMetadata, + publicMagicMetadata: { + ...publicMagicMetadata, + ...(uploaderName && { uploaderName }), + }, }; const { encryptedFilePieces, encryptedFileKey } = await encryptFile( @@ -1488,20 +1482,6 @@ const augmentWithThumbnail = async ( }; }; -const constructPublicMagicMetadata = async ( - publicMagicMetadataProps: FilePublicMagicMetadataData, -): Promise => { - const nonEmptyPublicMagicMetadataProps = getNonEmptyMagicMetadataProps( - publicMagicMetadataProps, - ); - - if (Object.values(nonEmptyPublicMagicMetadataProps).length === 0) { - // @ts-ignore - return null; - } - return await updateMagicMetadata(publicMagicMetadataProps); -}; - const encryptFile = async ( file: FileWithMetadata, collectionKey: string, @@ -1509,8 +1489,13 @@ const encryptFile = async ( ) => { const fileKey = await worker.generateBlobOrStreamKey(); - const { fileStreamOrData, thumbnail, metadata, pubMagicMetadata, localID } = - file; + const { + fileStreamOrData, + thumbnail, + metadata, + publicMagicMetadata, + localID, + } = file; const encryptedFiledata = fileStreamOrData instanceof Uint8Array @@ -1532,18 +1517,13 @@ const encryptFile = async ( fileKey, ); - let encryptedPubMagicMetadata: EncryptedMagicMetadata; - // Keep defensive check until the underlying type is audited. - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (pubMagicMetadata) { - const { encryptedData, decryptionHeader } = - await worker.encryptMetadataJSON(pubMagicMetadata.data, fileKey); - encryptedPubMagicMetadata = { - version: pubMagicMetadata.version, - count: pubMagicMetadata.count, - data: encryptedData, - header: decryptionHeader, - }; + let encryptedPubMagicMetadata: RemoteMagicMetadata | undefined; + const pubMagicMetadata = createMagicMetadata(publicMagicMetadata); + if (pubMagicMetadata.count) { + encryptedPubMagicMetadata = await encryptMagicMetadata( + pubMagicMetadata, + fileKey, + ); } const encryptedFileKey = await worker.encryptBox(fileKey, collectionKey); @@ -1553,7 +1533,6 @@ const encryptFile = async ( file: encryptedFiledata, thumbnail: encryptedThumbnail, metadata: encryptedMetadata, - // @ts-ignore pubMagicMetadata: encryptedPubMagicMetadata, localID: localID, }, diff --git a/web/packages/media/file.ts b/web/packages/media/file.ts index cf75fdbdfe..5e2a949ac5 100644 --- a/web/packages/media/file.ts +++ b/web/packages/media/file.ts @@ -511,12 +511,3 @@ export const mergeMetadata = (files: EnteFile[]) => */ export const fileLogID = (file: EnteFile) => `file ${fileFileName(file)} (${file.id})`; - -export interface MagicMetadataCore { - version: number; - count: number; - header: string; - data: T; -} - -export type EncryptedMagicMetadata = MagicMetadataCore; diff --git a/web/packages/new/photos/components/gallery/reducer.ts b/web/packages/new/photos/components/gallery/reducer.ts index fc6a397e69..84200af715 100644 --- a/web/packages/new/photos/components/gallery/reducer.ts +++ b/web/packages/new/photos/components/gallery/reducer.ts @@ -4,9 +4,13 @@ import { isPinnedCollection, } from "ente-gallery/services/magic-metadata"; import { collectionTypes, type Collection } from "ente-media/collection"; -import type { EnteFile, FilePrivateMagicMetadata } from "ente-media/file"; +import type { EnteFile } from "ente-media/file"; import { mergeMetadata } from "ente-media/file"; -import { isArchivedFile } from "ente-media/file-metadata"; +import { + isArchivedFile, + type FilePrivateMagicMetadataData, +} from "ente-media/file-metadata"; +import type { MagicMetadata } from "ente-media/magic-metadata"; import { createCollectionNameByID, isHiddenCollection, @@ -316,7 +320,10 @@ export interface GalleryState { * thereafter the synced files themselves will reflect the latest private * magic metadata. */ - unsyncedPrivateMagicMetadataUpdates: Map; + unsyncedPrivateMagicMetadataUpdates: Map< + number, + MagicMetadata + >; /*--< State that underlies transient UI state >--*/ @@ -447,7 +454,7 @@ export type GalleryAction = | { type: "unsyncedPrivateMagicMetadataUpdate"; fileID: number; - privateMagicMetadata: FilePrivateMagicMetadata; + privateMagicMetadata: MagicMetadata; } | { type: "clearUnsyncedState" } | { type: "showAll" }