diff --git a/web/apps/photos/src/services/upload/uploadManager.ts b/web/apps/photos/src/services/upload/uploadManager.ts index fd9307ae8..27888467d 100644 --- a/web/apps/photos/src/services/upload/uploadManager.ts +++ b/web/apps/photos/src/services/upload/uploadManager.ts @@ -1,3 +1,4 @@ +import { potentialFileTypeFromExtension } from "@/media/live-photo"; import { ensureElectron } from "@/next/electron"; import { nameAndExtension } from "@/next/file"; import log from "@/next/log"; @@ -57,7 +58,6 @@ import UploadService, { getFileName, uploader, } from "./uploadService"; -import { getFileTypeFromExtensionForLivePhotoClustering } from "utils/file/livePhoto"; const MAX_CONCURRENT_UPLOADS = 4; @@ -820,47 +820,32 @@ const clusterLivePhotos = (mediaFiles: FileWithCollection2[]) => { while (index < mediaFiles.length - 1) { const f = mediaFiles[index]; const g = mediaFiles[index + 1]; - const fFileType = getFileTypeFromExtensionForLivePhotoClustering( - getFileName(f.file), - ); - const gFileType = getFileTypeFromExtensionForLivePhotoClustering( - getFileName(g.file), - ); + const fFileName = getFileName(f.file); + const gFileName = getFileName(g.file); + const fFileType = potentialFileTypeFromExtension(fFileName); + const gFileType = potentialFileTypeFromExtension(gFileName); const fa: PotentialLivePhotoAsset = { - collectionID: f.collectionID, + fileName: fFileName, fileType: fFileType, - fileName: getFileName(f.file), + collectionID: f.collectionID, /* TODO(MR): ElectronFile changes */ size: (f as FileWithCollection).file.size, }; const ga: PotentialLivePhotoAsset = { - collectionID: g.collectionID, + fileName: gFileName, fileType: gFileType, - fileName: getFileName(g.file), + collectionID: g.collectionID, /* TODO(MR): ElectronFile changes */ size: (g as FileWithCollection).file.size, }; if (areLivePhotoAssets(fa, ga)) { - let imageFile: File | ElectronFile | string; - let videoFile: File | ElectronFile | string; - if ( - fFileType === FILE_TYPE.IMAGE && - gFileType === FILE_TYPE.VIDEO - ) { - imageFile = f.file; - videoFile = g.file; - } else { - videoFile = f.file; - imageFile = g.file; - } - const livePhotoLocalID = f.localID; result.push({ - localID: livePhotoLocalID, + localID: f.localID, collectionID: f.collectionID, isLivePhoto: true, livePhotoAssets: { - image: imageFile, - video: videoFile, + image: fFileType == FILE_TYPE.IMAGE ? f.file : g.file, + video: fFileType == FILE_TYPE.IMAGE ? g.file : f.file, }, }); index += 2; @@ -882,9 +867,9 @@ const clusterLivePhotos = (mediaFiles: FileWithCollection2[]) => { }; interface PotentialLivePhotoAsset { - collectionID: number; - fileType: FILE_TYPE; fileName: string; + fileType: FILE_TYPE; + collectionID: number; size: number; } diff --git a/web/apps/photos/src/utils/file/livePhoto.ts b/web/apps/photos/src/utils/file/livePhoto.ts deleted file mode 100644 index 7d687217c..000000000 --- a/web/apps/photos/src/utils/file/livePhoto.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { FILE_TYPE } from "constants/file"; -import { getFileExtension } from "utils/file"; - -const IMAGE_EXTENSIONS = [ - "heic", - "heif", - "jpeg", - "jpg", - "png", - "gif", - "bmp", - "tiff", - "webp", -]; - -const VIDEO_EXTENSIONS = [ - "mov", - "mp4", - "m4v", - "avi", - "wmv", - "flv", - "mkv", - "webm", - "3gp", - "3g2", - "avi", - "ogv", - "mpg", - "mp", -]; - -export function getFileTypeFromExtensionForLivePhotoClustering( - filename: string, -) { - const extension = getFileExtension(filename)?.toLowerCase(); - if (IMAGE_EXTENSIONS.includes(extension)) { - return FILE_TYPE.IMAGE; - } else if (VIDEO_EXTENSIONS.includes(extension)) { - return FILE_TYPE.VIDEO; - } -} diff --git a/web/packages/media/file.ts b/web/packages/media/file.ts new file mode 100644 index 000000000..8917db802 --- /dev/null +++ b/web/packages/media/file.ts @@ -0,0 +1,6 @@ +export enum FILE_TYPE { + IMAGE, + VIDEO, + LIVE_PHOTO, + OTHERS, +} diff --git a/web/packages/media/live-photo.ts b/web/packages/media/live-photo.ts index 16143ca13..c4a631467 100644 --- a/web/packages/media/live-photo.ts +++ b/web/packages/media/live-photo.ts @@ -1,5 +1,52 @@ import { fileNameFromComponents, nameAndExtension } from "@/next/file"; import JSZip from "jszip"; +import { FILE_TYPE } from "./file"; + +const potentialImageExtensions = [ + "heic", + "heif", + "jpeg", + "jpg", + "png", + "gif", + "bmp", + "tiff", + "webp", +]; + +const potentialVideoExtensions = [ + "mov", + "mp4", + "m4v", + "avi", + "wmv", + "flv", + "mkv", + "webm", + "3gp", + "3g2", + "avi", + "ogv", + "mpg", + "mp", +]; + +/** + * Use the file extension of the given {@link fileName} to deduce if is is + * potentially the image or the video part of a Live Photo. + */ +export const potentialFileTypeFromExtension = ( + fileName: string, +): FILE_TYPE | undefined => { + let [, ext] = nameAndExtension(fileName); + if (!ext) return undefined; + + ext = ext.toLowerCase(); + + if (potentialImageExtensions.includes(ext)) return FILE_TYPE.IMAGE; + else if (potentialVideoExtensions.includes(ext)) return FILE_TYPE.VIDEO; + else return undefined; +}; /** * An in-memory representation of a live photo.