Merge branch 'master' into code-scanning
This commit is contained in:
commit
721517c42d
|
@ -63,6 +63,7 @@ interface Props {
|
|||
activeCollection: number;
|
||||
isSharedCollection?: boolean;
|
||||
enableDownload?: boolean;
|
||||
isDeduplicating?: boolean;
|
||||
}
|
||||
|
||||
type SourceURL = {
|
||||
|
@ -87,6 +88,7 @@ const PhotoFrame = ({
|
|||
activeCollection,
|
||||
isSharedCollection,
|
||||
enableDownload,
|
||||
isDeduplicating,
|
||||
}: Props) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [currentIndex, setCurrentIndex] = useState<number>(0);
|
||||
|
@ -202,6 +204,7 @@ const PhotoFrame = ({
|
|||
return false;
|
||||
}
|
||||
if (
|
||||
!isDeduplicating &&
|
||||
activeCollection === ALL_SECTION &&
|
||||
(IsArchived(item) ||
|
||||
archivedCollections?.has(item.collectionID))
|
||||
|
@ -493,7 +496,9 @@ const PhotoFrame = ({
|
|||
|
||||
try {
|
||||
instance.invalidateCurrItems();
|
||||
instance.updateSize(true);
|
||||
if (instance.isOpen()) {
|
||||
instance.updateSize(true);
|
||||
}
|
||||
} catch (e) {
|
||||
logError(
|
||||
e,
|
||||
|
@ -551,7 +556,9 @@ const PhotoFrame = ({
|
|||
item.h = newFile.h;
|
||||
try {
|
||||
instance.invalidateCurrItems();
|
||||
instance.updateSize(true);
|
||||
if (instance.isOpen()) {
|
||||
instance.updateSize(true);
|
||||
}
|
||||
} catch (e) {
|
||||
logError(
|
||||
e,
|
||||
|
|
|
@ -18,7 +18,7 @@ export default function LeftArrow(props) {
|
|||
}
|
||||
|
||||
LeftArrow.defaultProps = {
|
||||
height: 28,
|
||||
width: 28,
|
||||
height: 24,
|
||||
width: 24,
|
||||
viewBox: '0 0 16 16',
|
||||
};
|
||||
|
|
|
@ -115,6 +115,7 @@ export const FileAndCollectionNameOverlay = styled.div`
|
|||
bottom: 0;
|
||||
left: 0;
|
||||
max-height: 40%;
|
||||
width: 100%;
|
||||
background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 2));
|
||||
& > p {
|
||||
max-width: calc(${IMAGE_CONTAINER_MAX_WIDTH}px - 10px);
|
||||
|
|
|
@ -8,6 +8,7 @@ import { DeduplicateContext } from 'pages/deduplicate';
|
|||
import LeftArrow from 'components/icons/LeftArrow';
|
||||
import { SetDialogMessage } from 'components/MessageDialog';
|
||||
import { IconWithMessage } from 'components/IconWithMessage';
|
||||
import CloseIcon from 'components/icons/CloseIcon';
|
||||
|
||||
const VerticalLine = styled.div`
|
||||
position: absolute;
|
||||
|
@ -28,6 +29,7 @@ interface IProps {
|
|||
setDialogMessage: SetDialogMessage;
|
||||
close: () => void;
|
||||
count: number;
|
||||
clearSelection: () => void;
|
||||
}
|
||||
|
||||
export default function DeduplicateOptions({
|
||||
|
@ -35,6 +37,7 @@ export default function DeduplicateOptions({
|
|||
deleteFileHelper,
|
||||
close,
|
||||
count,
|
||||
clearSelection,
|
||||
}: IProps) {
|
||||
const deduplicateContext = useContext(DeduplicateContext);
|
||||
|
||||
|
@ -54,9 +57,15 @@ export default function DeduplicateOptions({
|
|||
return (
|
||||
<SelectionBar>
|
||||
<SelectionContainer>
|
||||
<IconButton onClick={close}>
|
||||
<LeftArrow />
|
||||
</IconButton>
|
||||
{count ? (
|
||||
<IconButton onClick={clearSelection}>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
) : (
|
||||
<IconButton onClick={close}>
|
||||
<LeftArrow />
|
||||
</IconButton>
|
||||
)}
|
||||
<div>
|
||||
{count} {constants.SELECTED}
|
||||
</div>
|
||||
|
|
|
@ -146,6 +146,10 @@ export default function Deduplicate() {
|
|||
}
|
||||
};
|
||||
|
||||
const clearSelection = function () {
|
||||
setSelected({ count: 0, collectionID: 0 });
|
||||
};
|
||||
|
||||
if (!duplicateFiles) {
|
||||
return <></>;
|
||||
}
|
||||
|
@ -177,12 +181,14 @@ export default function Deduplicate() {
|
|||
setSelected={setSelected}
|
||||
selected={selected}
|
||||
activeCollection={ALL_SECTION}
|
||||
isDeduplicating
|
||||
/>
|
||||
<DeduplicateOptions
|
||||
setDialogMessage={setDialogMessage}
|
||||
deleteFileHelper={deleteFileHelper}
|
||||
count={selected.count}
|
||||
close={closeDeduplication}
|
||||
clearSelection={clearSelection}
|
||||
/>
|
||||
</DeduplicateContext.Provider>
|
||||
);
|
||||
|
|
|
@ -4,7 +4,6 @@ import { parseFFmpegExtractedMetadata } from 'utils/ffmpeg';
|
|||
|
||||
class FFmpegClient {
|
||||
private ffmpeg: FFmpeg;
|
||||
private fileReader: FileReader;
|
||||
private ready: Promise<void> = null;
|
||||
constructor() {
|
||||
this.ffmpeg = createFFmpeg({
|
||||
|
@ -19,9 +18,6 @@ class FFmpegClient {
|
|||
if (!this.ffmpeg.isLoaded()) {
|
||||
await this.ffmpeg.load();
|
||||
}
|
||||
if (!this.fileReader) {
|
||||
this.fileReader = new FileReader();
|
||||
}
|
||||
}
|
||||
|
||||
async generateThumbnail(file: File) {
|
||||
|
@ -31,7 +27,7 @@ class FFmpegClient {
|
|||
this.ffmpeg.FS(
|
||||
'writeFile',
|
||||
inputFileName,
|
||||
await getUint8ArrayView(this.fileReader, file)
|
||||
await getUint8ArrayView(file)
|
||||
);
|
||||
let seekTime = 1.0;
|
||||
let thumb = null;
|
||||
|
@ -66,7 +62,7 @@ class FFmpegClient {
|
|||
this.ffmpeg.FS(
|
||||
'writeFile',
|
||||
inputFileName,
|
||||
await getUint8ArrayView(this.fileReader, file)
|
||||
await getUint8ArrayView(file)
|
||||
);
|
||||
let metadata = null;
|
||||
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import * as HeicConvert from 'heic-convert';
|
||||
import { getUint8ArrayView } from 'services/readerService';
|
||||
|
||||
export async function convertHEIC(
|
||||
fileBlob: Blob,
|
||||
format: string
|
||||
): Promise<Blob> {
|
||||
const filedata = new Uint8Array(await fileBlob.arrayBuffer());
|
||||
const filedata = await getUint8ArrayView(fileBlob);
|
||||
const result = await HeicConvert({ buffer: filedata, format });
|
||||
const convertedFileData = new Uint8Array(result);
|
||||
const convertedFileBlob = new Blob([convertedFileData]);
|
||||
|
|
|
@ -44,7 +44,6 @@ export async function replaceThumbnail(
|
|||
try {
|
||||
const token = getToken();
|
||||
const worker = await new CryptoWorker();
|
||||
const reader = new FileReader();
|
||||
const files = await getLocalFiles();
|
||||
const trash = await getLocalTrash();
|
||||
const trashFiles = getTrashedFiles(trash);
|
||||
|
@ -77,9 +76,8 @@ export async function replaceThumbnail(
|
|||
[originalThumbnail],
|
||||
file.metadata.title
|
||||
);
|
||||
const fileTypeInfo = await getFileType(reader, dummyImageFile);
|
||||
const fileTypeInfo = await getFileType(dummyImageFile);
|
||||
const { thumbnail: newThumbnail } = await generateThumbnail(
|
||||
reader,
|
||||
dummyImageFile,
|
||||
fileTypeInfo
|
||||
);
|
||||
|
|
|
@ -1,6 +1,79 @@
|
|||
import { ElectronFile } from 'types/upload';
|
||||
import { logError } from 'utils/sentry';
|
||||
|
||||
export async function getUint8ArrayView(
|
||||
file: Blob | ElectronFile
|
||||
): Promise<Uint8Array> {
|
||||
try {
|
||||
return new Uint8Array(await file.arrayBuffer());
|
||||
} catch (e) {
|
||||
logError(e, 'reading file blob failed', {
|
||||
fileSize: convertBytesToHumanReadable(file.size),
|
||||
});
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
export function getFileStream(file: File, chunkSize: number) {
|
||||
const fileChunkReader = fileChunkReaderMaker(file, chunkSize);
|
||||
|
||||
const stream = new ReadableStream<Uint8Array>({
|
||||
async pull(controller: ReadableStreamDefaultController) {
|
||||
const chunk = await fileChunkReader.next();
|
||||
if (chunk.done) {
|
||||
controller.close();
|
||||
} else {
|
||||
controller.enqueue(chunk.value);
|
||||
}
|
||||
},
|
||||
});
|
||||
const chunkCount = Math.ceil(file.size / chunkSize);
|
||||
return {
|
||||
stream,
|
||||
chunkCount,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getElectronFileStream(
|
||||
file: ElectronFile,
|
||||
chunkSize: number
|
||||
) {
|
||||
const chunkCount = Math.ceil(file.size / chunkSize);
|
||||
return {
|
||||
stream: await file.stream(),
|
||||
chunkCount,
|
||||
};
|
||||
}
|
||||
|
||||
async function* fileChunkReaderMaker(file: File, chunkSize: number) {
|
||||
let offset = 0;
|
||||
while (offset < file.size) {
|
||||
const blob = file.slice(offset, chunkSize + offset);
|
||||
const fileChunk = await getUint8ArrayView(blob);
|
||||
yield fileChunk;
|
||||
offset += chunkSize;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Temporary fix for window not defined caused on importing from utils/billing
|
||||
// because this file is accessed inside worker and util/billing imports constants
|
||||
// which has reference to window object, which cause error inside worker
|
||||
// TODO: update worker to not read file themselves but rather have filedata passed to them
|
||||
|
||||
function convertBytesToHumanReadable(bytes: number, precision = 2): string {
|
||||
if (bytes === 0) {
|
||||
return '0 MB';
|
||||
}
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
|
||||
return (bytes / Math.pow(1024, i)).toFixed(precision) + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
// depreciated
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async function getUint8ArrayViewOld(
|
||||
reader: FileReader,
|
||||
file: Blob
|
||||
): Promise<Uint8Array> {
|
||||
|
@ -32,71 +105,3 @@ export async function getUint8ArrayView(
|
|||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
}
|
||||
|
||||
export function getFileStream(
|
||||
reader: FileReader,
|
||||
file: File,
|
||||
chunkSize: number
|
||||
) {
|
||||
const fileChunkReader = fileChunkReaderMaker(reader, file, chunkSize);
|
||||
|
||||
const stream = new ReadableStream<Uint8Array>({
|
||||
async pull(controller: ReadableStreamDefaultController) {
|
||||
const chunk = await fileChunkReader.next();
|
||||
if (chunk.done) {
|
||||
controller.close();
|
||||
} else {
|
||||
controller.enqueue(chunk.value);
|
||||
}
|
||||
},
|
||||
});
|
||||
const chunkCount = Math.ceil(file.size / chunkSize);
|
||||
return {
|
||||
stream,
|
||||
chunkCount,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getElectronFileStream(
|
||||
file: ElectronFile,
|
||||
chunkSize: number
|
||||
) {
|
||||
const chunkCount = Math.ceil(file.size / chunkSize);
|
||||
return {
|
||||
stream: await file.stream(),
|
||||
chunkCount,
|
||||
};
|
||||
}
|
||||
|
||||
async function* fileChunkReaderMaker(
|
||||
reader: FileReader,
|
||||
file: File,
|
||||
chunkSize: number
|
||||
) {
|
||||
let offset = 0;
|
||||
while (offset < file.size) {
|
||||
const blob = file.slice(offset, chunkSize + offset);
|
||||
const fileChunk = await getUint8ArrayView(reader, blob);
|
||||
yield fileChunk;
|
||||
offset += chunkSize;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Temporary fix for window not defined caused on importing from utils/billing
|
||||
// because this file is accessed inside worker and util/billing imports constants
|
||||
// which has reference to window object, which cause error inside worker
|
||||
// TODO: update worker to not read file themselves but rather have filedata passed to them
|
||||
|
||||
export function convertBytesToHumanReadable(
|
||||
bytes: number,
|
||||
precision = 2
|
||||
): string {
|
||||
if (bytes === 0) {
|
||||
return '0 MB';
|
||||
}
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
|
||||
return (bytes / Math.pow(1024, i)).toFixed(precision) + ' ' + sizes[i];
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ const TYPE_IMAGE = 'image';
|
|||
const CHUNK_SIZE_FOR_TYPE_DETECTION = 4100;
|
||||
|
||||
export async function getFileType(
|
||||
reader: FileReader,
|
||||
receivedFile: File | ElectronFile
|
||||
): Promise<FileTypeInfo> {
|
||||
try {
|
||||
|
@ -20,7 +19,7 @@ export async function getFileType(
|
|||
let typeResult: FileTypeResult;
|
||||
|
||||
if (receivedFile instanceof File) {
|
||||
typeResult = await extractFileType(reader, receivedFile);
|
||||
typeResult = await extractFileType(receivedFile);
|
||||
} else {
|
||||
typeResult = await extractElectronFileType(receivedFile);
|
||||
}
|
||||
|
@ -64,9 +63,9 @@ export async function getFileType(
|
|||
}
|
||||
}
|
||||
|
||||
async function extractFileType(reader: FileReader, file: File) {
|
||||
async function extractFileType(file: File) {
|
||||
const fileChunkBlob = file.slice(0, CHUNK_SIZE_FOR_TYPE_DETECTION);
|
||||
return getFileTypeFromBlob(reader, fileChunkBlob);
|
||||
return getFileTypeFromBlob(fileChunkBlob);
|
||||
}
|
||||
|
||||
async function extractElectronFileType(file: ElectronFile) {
|
||||
|
@ -77,9 +76,9 @@ async function extractElectronFileType(file: ElectronFile) {
|
|||
return fileTypeResult;
|
||||
}
|
||||
|
||||
async function getFileTypeFromBlob(reader: FileReader, fileBlob: Blob) {
|
||||
async function getFileTypeFromBlob(fileBlob: Blob) {
|
||||
try {
|
||||
const initialFiledata = await getUint8ArrayView(reader, fileBlob);
|
||||
const initialFiledata = await getUint8ArrayView(fileBlob);
|
||||
return await FileType.fromBuffer(initialFiledata);
|
||||
} catch (e) {
|
||||
throw Error(CustomError.TYPE_DETECTION_FAILED);
|
||||
|
|
|
@ -38,8 +38,7 @@ export async function updateCreationTimeWithExif(
|
|||
} else {
|
||||
const fileURL = await downloadManager.getFile(file)[0];
|
||||
const fileObject = await getFileFromURL(fileURL);
|
||||
const reader = new FileReader();
|
||||
const fileTypeInfo = await getFileType(reader, fileObject);
|
||||
const fileTypeInfo = await getFileType(fileObject);
|
||||
const exifData = await getRawExif(fileObject, fileTypeInfo);
|
||||
if (fixOption === FIX_OPTIONS.DATE_TIME_ORIGINAL) {
|
||||
correctCreationTime = getUnixTimeInMicroSeconds(
|
||||
|
|
|
@ -34,12 +34,10 @@ export function getFilename(file: File | ElectronFile) {
|
|||
}
|
||||
|
||||
export async function readFile(
|
||||
reader: FileReader,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
rawFile: File | ElectronFile
|
||||
): Promise<FileInMemory> {
|
||||
const { thumbnail, hasStaticThumbnail } = await generateThumbnail(
|
||||
reader,
|
||||
rawFile,
|
||||
fileTypeInfo
|
||||
);
|
||||
|
@ -52,12 +50,12 @@ export async function readFile(
|
|||
FILE_READER_CHUNK_SIZE
|
||||
);
|
||||
} else {
|
||||
filedata = await rawFile.arrayBuffer();
|
||||
filedata = await getUint8ArrayView(rawFile);
|
||||
}
|
||||
} else if (rawFile.size > MULTIPART_PART_SIZE) {
|
||||
filedata = getFileStream(reader, rawFile, FILE_READER_CHUNK_SIZE);
|
||||
filedata = getFileStream(rawFile, FILE_READER_CHUNK_SIZE);
|
||||
} else {
|
||||
filedata = await getUint8ArrayView(reader, rawFile);
|
||||
filedata = await getUint8ArrayView(rawFile);
|
||||
}
|
||||
|
||||
logUploadInfo(`read file data successfully ${getFileNameSize(rawFile)} `);
|
||||
|
@ -73,8 +71,7 @@ export async function extractFileMetadata(
|
|||
parsedMetadataJSONMap: ParsedMetadataJSONMap,
|
||||
rawFile: File | ElectronFile,
|
||||
collectionID: number,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
reader: FileReader
|
||||
fileTypeInfo: FileTypeInfo
|
||||
) {
|
||||
const originalName = getFileOriginalName(rawFile);
|
||||
const googleMetadata =
|
||||
|
@ -83,8 +80,7 @@ export async function extractFileMetadata(
|
|||
) ?? {};
|
||||
const extractedMetadata: Metadata = await extractMetadata(
|
||||
rawFile,
|
||||
fileTypeInfo,
|
||||
reader
|
||||
fileTypeInfo
|
||||
);
|
||||
|
||||
for (const [key, value] of Object.entries(googleMetadata)) {
|
||||
|
|
|
@ -72,12 +72,10 @@ export function getLivePhotoName(imageTitle: string) {
|
|||
}
|
||||
|
||||
export async function readLivePhoto(
|
||||
reader: FileReader,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
livePhotoAssets: LivePhotoAssets
|
||||
) {
|
||||
const { thumbnail, hasStaticThumbnail } = await generateThumbnail(
|
||||
reader,
|
||||
livePhotoAssets.image,
|
||||
{
|
||||
exactType: fileTypeInfo.imageType,
|
||||
|
@ -85,15 +83,9 @@ export async function readLivePhoto(
|
|||
}
|
||||
);
|
||||
|
||||
const image =
|
||||
livePhotoAssets.image instanceof File
|
||||
? await getUint8ArrayView(reader, livePhotoAssets.image)
|
||||
: await livePhotoAssets.image.arrayBuffer();
|
||||
const image = await getUint8ArrayView(livePhotoAssets.image);
|
||||
|
||||
const video =
|
||||
livePhotoAssets.video instanceof File
|
||||
? await getUint8ArrayView(reader, livePhotoAssets.video)
|
||||
: await livePhotoAssets.video.arrayBuffer();
|
||||
const video = await getUint8ArrayView(livePhotoAssets.video);
|
||||
|
||||
return {
|
||||
filedata: await encodeMotionPhoto({
|
||||
|
|
|
@ -33,8 +33,7 @@ const NULL_PARSED_METADATA_JSON: ParsedMetadataJSON = {
|
|||
|
||||
export async function extractMetadata(
|
||||
receivedFile: File | ElectronFile,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
reader: FileReader
|
||||
fileTypeInfo: FileTypeInfo
|
||||
) {
|
||||
let extractedMetadata: ParsedExtractedMetadata = NULL_EXTRACTED_METADATA;
|
||||
if (fileTypeInfo.fileType === FILE_TYPE.IMAGE) {
|
||||
|
@ -51,7 +50,7 @@ export async function extractMetadata(
|
|||
);
|
||||
}
|
||||
|
||||
const fileHash = await getFileHash(receivedFile, reader);
|
||||
const fileHash = await getFileHash(receivedFile);
|
||||
|
||||
const metadata: Metadata = {
|
||||
title: receivedFile.name,
|
||||
|
@ -74,10 +73,7 @@ export const getMetadataJSONMapKey = (
|
|||
title: string
|
||||
) => `${collectionID}-${title}`;
|
||||
|
||||
export async function parseMetadataJSON(
|
||||
reader: FileReader,
|
||||
receivedFile: File | ElectronFile
|
||||
) {
|
||||
export async function parseMetadataJSON(receivedFile: File | ElectronFile) {
|
||||
try {
|
||||
if (!(receivedFile instanceof File)) {
|
||||
receivedFile = new File(
|
||||
|
@ -85,18 +81,7 @@ export async function parseMetadataJSON(
|
|||
receivedFile.name
|
||||
);
|
||||
}
|
||||
const metadataJSON: object = await new Promise((resolve, reject) => {
|
||||
reader.onabort = () => reject(Error('file reading was aborted'));
|
||||
reader.onerror = () => reject(Error('file reading has failed'));
|
||||
reader.onload = () => {
|
||||
const result =
|
||||
typeof reader.result !== 'string'
|
||||
? new TextDecoder().decode(reader.result)
|
||||
: reader.result;
|
||||
resolve(JSON.parse(result));
|
||||
};
|
||||
reader.readAsText(receivedFile as File);
|
||||
});
|
||||
const metadataJSON: object = JSON.parse(await receivedFile.text());
|
||||
|
||||
const parsedMetadataJSON: ParsedMetadataJSON =
|
||||
NULL_PARSED_METADATA_JSON;
|
||||
|
|
|
@ -24,7 +24,6 @@ interface Dimension {
|
|||
}
|
||||
|
||||
export async function generateThumbnail(
|
||||
reader: FileReader,
|
||||
file: File | ElectronFile,
|
||||
fileTypeInfo: FileTypeInfo
|
||||
): Promise<{ thumbnail: Uint8Array; hasStaticThumbnail: boolean }> {
|
||||
|
@ -72,7 +71,7 @@ export async function generateThumbnail(
|
|||
}
|
||||
}
|
||||
const thumbnailBlob = await thumbnailCanvasToBlob(canvas);
|
||||
thumbnail = await getUint8ArrayView(reader, thumbnailBlob);
|
||||
thumbnail = await getUint8ArrayView(thumbnailBlob);
|
||||
if (thumbnail.length === 0) {
|
||||
throw Error('EMPTY THUMBNAIL');
|
||||
}
|
||||
|
|
|
@ -157,7 +157,7 @@ class UploadManager {
|
|||
logUploadInfo(`parseMetadataJSONFiles function executed `);
|
||||
|
||||
UIService.reset(metadataFiles.length);
|
||||
const reader = new FileReader();
|
||||
|
||||
for (const { file, collectionID } of metadataFiles) {
|
||||
try {
|
||||
logUploadInfo(
|
||||
|
@ -165,7 +165,6 @@ class UploadManager {
|
|||
);
|
||||
|
||||
const parsedMetadataJSONWithTitle = await parseMetadataJSON(
|
||||
reader,
|
||||
file
|
||||
);
|
||||
if (parsedMetadataJSONWithTitle) {
|
||||
|
@ -201,7 +200,6 @@ class UploadManager {
|
|||
try {
|
||||
logUploadInfo(`extractMetadataFromFiles executed`);
|
||||
UIService.reset(mediaFiles.length);
|
||||
const reader = new FileReader();
|
||||
for (const { file, localID, collectionID } of mediaFiles) {
|
||||
try {
|
||||
const { fileTypeInfo, metadata } = await (async () => {
|
||||
|
@ -215,7 +213,6 @@ class UploadManager {
|
|||
return { fileTypeInfo: null, metadata: null };
|
||||
}
|
||||
const fileTypeInfo = await UploadService.getFileType(
|
||||
reader,
|
||||
file
|
||||
);
|
||||
if (fileTypeInfo.fileType === FILE_TYPE.OTHERS) {
|
||||
|
@ -233,8 +230,7 @@ class UploadManager {
|
|||
(await UploadService.extractFileMetadata(
|
||||
file,
|
||||
collectionID,
|
||||
fileTypeInfo,
|
||||
reader
|
||||
fileTypeInfo
|
||||
)) || null;
|
||||
return { fileTypeInfo, metadata };
|
||||
})();
|
||||
|
@ -291,15 +287,14 @@ class UploadManager {
|
|||
this.cryptoWorkers[i] = cryptoWorker;
|
||||
uploadProcesses.push(
|
||||
this.uploadNextFileInQueue(
|
||||
await new this.cryptoWorkers[i].comlink(),
|
||||
new FileReader()
|
||||
await new this.cryptoWorkers[i].comlink()
|
||||
)
|
||||
);
|
||||
}
|
||||
await Promise.all(uploadProcesses);
|
||||
}
|
||||
|
||||
private async uploadNextFileInQueue(worker: any, reader: FileReader) {
|
||||
private async uploadNextFileInQueue(worker: any) {
|
||||
while (this.filesToBeUploaded.length > 0) {
|
||||
let fileWithCollection = this.filesToBeUploaded.pop();
|
||||
const { collectionID } = fileWithCollection;
|
||||
|
@ -310,7 +305,6 @@ class UploadManager {
|
|||
const { fileUploadResult, uploadedFile, skipDecryption } =
|
||||
await uploader(
|
||||
worker,
|
||||
reader,
|
||||
existingFilesInCollection,
|
||||
this.existingFiles,
|
||||
fileWithCollection
|
||||
|
|
|
@ -76,32 +76,29 @@ class UploadService {
|
|||
: getFilename(file);
|
||||
}
|
||||
|
||||
async getFileType(reader: FileReader, file: File | ElectronFile) {
|
||||
return getFileType(reader, file);
|
||||
async getFileType(file: File | ElectronFile) {
|
||||
return getFileType(file);
|
||||
}
|
||||
|
||||
async readAsset(
|
||||
reader: FileReader,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
{ isLivePhoto, file, livePhotoAssets }: UploadAsset
|
||||
) {
|
||||
return isLivePhoto
|
||||
? await readLivePhoto(reader, fileTypeInfo, livePhotoAssets)
|
||||
: await readFile(reader, fileTypeInfo, file);
|
||||
? await readLivePhoto(fileTypeInfo, livePhotoAssets)
|
||||
: await readFile(fileTypeInfo, file);
|
||||
}
|
||||
|
||||
async extractFileMetadata(
|
||||
file: File | ElectronFile,
|
||||
collectionID: number,
|
||||
fileTypeInfo: FileTypeInfo,
|
||||
reader: FileReader
|
||||
fileTypeInfo: FileTypeInfo
|
||||
): Promise<Metadata> {
|
||||
return extractFileMetadata(
|
||||
this.parsedMetadataJSONMap,
|
||||
file,
|
||||
collectionID,
|
||||
fileTypeInfo,
|
||||
reader
|
||||
fileTypeInfo
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ interface UploadResponse {
|
|||
}
|
||||
export default async function uploader(
|
||||
worker: any,
|
||||
reader: FileReader,
|
||||
existingFilesInCollection: EnteFile[],
|
||||
existingFiles: EnteFile[],
|
||||
fileWithCollection: FileWithCollection
|
||||
|
@ -87,11 +86,7 @@ export default async function uploader(
|
|||
}
|
||||
logUploadInfo(`reading asset ${fileNameSize}`);
|
||||
|
||||
const file = await UploadService.readAsset(
|
||||
reader,
|
||||
fileTypeInfo,
|
||||
uploadAsset
|
||||
);
|
||||
const file = await UploadService.readAsset(fileTypeInfo, uploadAsset);
|
||||
|
||||
if (file.hasStaticThumbnail) {
|
||||
metadata.hasStaticThumbnail = true;
|
||||
|
|
|
@ -201,13 +201,10 @@ export async function encryptWithRecoveryKey(key: string) {
|
|||
}
|
||||
export default CryptoWorker;
|
||||
|
||||
export async function getFileHash(
|
||||
file: File | ElectronFile,
|
||||
reader: FileReader
|
||||
) {
|
||||
export async function getFileHash(file: File | ElectronFile) {
|
||||
let filedata: DataStream;
|
||||
if (file instanceof File) {
|
||||
filedata = getFileStream(reader, file, FILE_READER_CHUNK_SIZE);
|
||||
filedata = getFileStream(file, FILE_READER_CHUNK_SIZE);
|
||||
} else {
|
||||
filedata = await getElectronFileStream(file, FILE_READER_CHUNK_SIZE);
|
||||
}
|
||||
|
|
|
@ -77,7 +77,6 @@ export async function downloadFile(
|
|||
}
|
||||
|
||||
const fileType = await getFileType(
|
||||
fileReader,
|
||||
new File([fileBlob], file.metadata.title)
|
||||
);
|
||||
if (
|
||||
|
@ -98,12 +97,12 @@ export async function downloadFile(
|
|||
const originalName = fileNameWithoutExtension(file.metadata.title);
|
||||
const motionPhoto = await decodeMotionPhoto(fileBlob, originalName);
|
||||
const image = new File([motionPhoto.image], motionPhoto.imageNameTitle);
|
||||
const imageType = await getFileType(fileReader, image);
|
||||
const imageType = await getFileType(image);
|
||||
tempImageURL = URL.createObjectURL(
|
||||
new Blob([motionPhoto.image], { type: imageType.mimeType })
|
||||
);
|
||||
const video = new File([motionPhoto.video], motionPhoto.videoNameTitle);
|
||||
const videoType = await getFileType(fileReader, video);
|
||||
const videoType = await getFileType(video);
|
||||
tempVideoURL = URL.createObjectURL(
|
||||
new Blob([motionPhoto.video], { type: videoType.mimeType })
|
||||
);
|
||||
|
@ -338,9 +337,8 @@ export async function convertForPreview(
|
|||
fileBlob: Blob
|
||||
): Promise<Blob[]> {
|
||||
const convertIfHEIC = async (fileName: string, fileBlob: Blob) => {
|
||||
const reader = new FileReader();
|
||||
const mimeType = (
|
||||
await getFileType(reader, new File([fileBlob], file.metadata.title))
|
||||
await getFileType(new File([fileBlob], file.metadata.title))
|
||||
).exactType;
|
||||
if (isFileHEIC(mimeType)) {
|
||||
fileBlob = await HEICConverter.convert(fileBlob);
|
||||
|
|
2
thirdparty/photoswipe
vendored
2
thirdparty/photoswipe
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 59bf9ab3fc462c543d14d714b6f28f2d3bf8596c
|
||||
Subproject commit bf4a072503df18c8d6b047e66a437534c5c05bc5
|
Loading…
Reference in a new issue