Handle new motion photo import image name format (#1399)
This commit is contained in:
commit
618cf574cc
|
@ -1,6 +1,9 @@
|
|||
import JSZip from 'jszip';
|
||||
import { EnteFile } from 'types/file';
|
||||
import { fileExtensionWithDot, fileNameWithoutExtension } from 'utils/file';
|
||||
import {
|
||||
getFileExtensionWithDot,
|
||||
getFileNameWithoutExtension,
|
||||
} from 'utils/file';
|
||||
|
||||
class LivePhoto {
|
||||
image: Uint8Array;
|
||||
|
@ -10,18 +13,18 @@ class LivePhoto {
|
|||
}
|
||||
|
||||
export const decodeLivePhoto = async (file: EnteFile, zipBlob: Blob) => {
|
||||
const originalName = fileNameWithoutExtension(file.metadata.title);
|
||||
const originalName = getFileNameWithoutExtension(file.metadata.title);
|
||||
const zip = await JSZip.loadAsync(zipBlob, { createFolders: true });
|
||||
|
||||
const livePhoto = new LivePhoto();
|
||||
for (const zipFilename in zip.files) {
|
||||
if (zipFilename.startsWith('image')) {
|
||||
livePhoto.imageNameTitle =
|
||||
originalName + fileExtensionWithDot(zipFilename);
|
||||
originalName + getFileExtensionWithDot(zipFilename);
|
||||
livePhoto.image = await zip.files[zipFilename].async('uint8array');
|
||||
} else if (zipFilename.startsWith('video')) {
|
||||
livePhoto.videoNameTitle =
|
||||
originalName + fileExtensionWithDot(zipFilename);
|
||||
originalName + getFileExtensionWithDot(zipFilename);
|
||||
livePhoto.video = await zip.files[zipFilename].async('uint8array');
|
||||
}
|
||||
}
|
||||
|
@ -31,11 +34,11 @@ export const decodeLivePhoto = async (file: EnteFile, zipBlob: Blob) => {
|
|||
export const encodeLivePhoto = async (livePhoto: LivePhoto) => {
|
||||
const zip = new JSZip();
|
||||
zip.file(
|
||||
'image' + fileExtensionWithDot(livePhoto.imageNameTitle),
|
||||
'image' + getFileExtensionWithDot(livePhoto.imageNameTitle),
|
||||
livePhoto.image
|
||||
);
|
||||
zip.file(
|
||||
'video' + fileExtensionWithDot(livePhoto.videoNameTitle),
|
||||
'video' + getFileExtensionWithDot(livePhoto.videoNameTitle),
|
||||
livePhoto.video
|
||||
);
|
||||
return await zip.generateAsync({ type: 'uint8array' });
|
||||
|
|
|
@ -12,7 +12,12 @@ import {
|
|||
} from 'types/upload';
|
||||
import { CustomError } from 'utils/error';
|
||||
import { getFileTypeFromExtensionForLivePhotoClustering } from 'utils/file/livePhoto';
|
||||
import { splitFilenameAndExtension, isImageOrVideo } from 'utils/file';
|
||||
import {
|
||||
splitFilenameAndExtension,
|
||||
isImageOrVideo,
|
||||
getFileExtensionWithDot,
|
||||
getFileNameWithoutExtension,
|
||||
} from 'utils/file';
|
||||
import { logError } from 'utils/sentry';
|
||||
import { getUint8ArrayView } from '../readerService';
|
||||
import { extractFileMetadata } from './fileService';
|
||||
|
@ -33,7 +38,6 @@ const UNDERSCORE_THREE = '_3';
|
|||
// Note: The icloud-photos-downloader library appends _HVEC to the end of the filename in case of live photos
|
||||
// https://github.com/icloud-photos-downloader/icloud_photos_downloader
|
||||
const UNDERSCORE_HEVC = '_HVEC';
|
||||
const UNDERSCORE = '_';
|
||||
|
||||
export async function getLivePhotoFileType(
|
||||
livePhotoAssets: LivePhotoAssets
|
||||
|
@ -219,18 +223,38 @@ function areFilesLivePhotoAssets(
|
|||
firstFileIdentifier: LivePhotoIdentifier,
|
||||
secondFileIdentifier: LivePhotoIdentifier
|
||||
) {
|
||||
const haveSameCollectionID =
|
||||
firstFileIdentifier.collectionID === secondFileIdentifier.collectionID;
|
||||
const areNotSameFileType =
|
||||
firstFileIdentifier.fileType !== secondFileIdentifier.fileType;
|
||||
|
||||
let firstFileNameWithoutSuffix: string;
|
||||
let secondFileNameWithoutSuffix: string;
|
||||
if (firstFileIdentifier.fileType === FILE_TYPE.IMAGE) {
|
||||
firstFileNameWithoutSuffix = removePotentialLivePhotoSuffix(
|
||||
getFileNameWithoutExtension(firstFileIdentifier.name),
|
||||
// Note: The Google Live Photo image file can have video extension appended as suffix, passing that to removePotentialLivePhotoSuffix to remove it
|
||||
// Example: IMG_20210630_0001.mp4.jpg (Google Live Photo image file)
|
||||
getFileExtensionWithDot(secondFileIdentifier.name)
|
||||
);
|
||||
secondFileNameWithoutSuffix = removePotentialLivePhotoSuffix(
|
||||
getFileNameWithoutExtension(secondFileIdentifier.name)
|
||||
);
|
||||
} else {
|
||||
firstFileNameWithoutSuffix = removePotentialLivePhotoSuffix(
|
||||
getFileNameWithoutExtension(firstFileIdentifier.name)
|
||||
);
|
||||
secondFileNameWithoutSuffix = removePotentialLivePhotoSuffix(
|
||||
getFileNameWithoutExtension(secondFileIdentifier.name),
|
||||
getFileExtensionWithDot(firstFileIdentifier.name)
|
||||
);
|
||||
}
|
||||
if (
|
||||
firstFileIdentifier.collectionID ===
|
||||
secondFileIdentifier.collectionID &&
|
||||
firstFileIdentifier.fileType !== secondFileIdentifier.fileType &&
|
||||
haveSameCollectionID &&
|
||||
isImageOrVideo(firstFileIdentifier.fileType) &&
|
||||
isImageOrVideo(secondFileIdentifier.fileType) &&
|
||||
removePotentailLivePhotoSuffix(
|
||||
splitFilenameAndExtension(firstFileIdentifier.name)[0]
|
||||
) ===
|
||||
removePotentailLivePhotoSuffix(
|
||||
splitFilenameAndExtension(secondFileIdentifier.name)[0]
|
||||
)
|
||||
areNotSameFileType &&
|
||||
firstFileNameWithoutSuffix === secondFileNameWithoutSuffix
|
||||
) {
|
||||
// checks size of live Photo assets are less than allowed limit
|
||||
// I did that based on the assumption that live photo assets ideally would not be larger than LIVE_PHOTO_ASSET_SIZE_LIMIT
|
||||
|
@ -256,11 +280,29 @@ function areFilesLivePhotoAssets(
|
|||
return false;
|
||||
}
|
||||
|
||||
function removePotentailLivePhotoSuffix(filename: string) {
|
||||
if (filename.endsWith(UNDERSCORE_THREE)) {
|
||||
return filename.slice(0, filename.lastIndexOf(UNDERSCORE));
|
||||
} else if (filename.toLowerCase().endsWith(UNDERSCORE_HEVC)) {
|
||||
return filename.slice(0, filename.lastIndexOf(UNDERSCORE_HEVC));
|
||||
function removePotentialLivePhotoSuffix(
|
||||
filenameWithoutExtension: string,
|
||||
suffix?: string
|
||||
) {
|
||||
let presentSuffix: string;
|
||||
if (filenameWithoutExtension.endsWith(UNDERSCORE_THREE)) {
|
||||
presentSuffix = UNDERSCORE_THREE;
|
||||
} else if (filenameWithoutExtension.endsWith(UNDERSCORE_HEVC)) {
|
||||
presentSuffix = UNDERSCORE_HEVC;
|
||||
} else if (
|
||||
filenameWithoutExtension.endsWith(UNDERSCORE_HEVC.toLowerCase())
|
||||
) {
|
||||
presentSuffix = UNDERSCORE_HEVC.toLowerCase();
|
||||
} else if (suffix) {
|
||||
if (filenameWithoutExtension.endsWith(suffix)) {
|
||||
presentSuffix = suffix;
|
||||
} else if (filenameWithoutExtension.endsWith(suffix.toLowerCase())) {
|
||||
presentSuffix = suffix.toLowerCase();
|
||||
}
|
||||
}
|
||||
if (presentSuffix) {
|
||||
return filenameWithoutExtension.slice(0, presentSuffix.length * -1);
|
||||
} else {
|
||||
return filenameWithoutExtension;
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
|
|
@ -292,13 +292,13 @@ export async function decryptFile(
|
|||
}
|
||||
}
|
||||
|
||||
export function fileNameWithoutExtension(filename: string) {
|
||||
export function getFileNameWithoutExtension(filename: string) {
|
||||
const lastDotPosition = filename.lastIndexOf('.');
|
||||
if (lastDotPosition === -1) return filename;
|
||||
else return filename.slice(0, lastDotPosition);
|
||||
}
|
||||
|
||||
export function fileExtensionWithDot(filename: string) {
|
||||
export function getFileExtensionWithDot(filename: string) {
|
||||
const lastDotPosition = filename.lastIndexOf('.');
|
||||
if (lastDotPosition === -1) return '';
|
||||
else return filename.slice(lastDotPosition);
|
||||
|
|
Loading…
Reference in a new issue