2021-10-08 14:26:49 +00:00
|
|
|
import downloadManager from 'services/downloadManager';
|
2021-10-18 05:37:59 +00:00
|
|
|
import { fileAttribute, FILE_TYPE, getLocalFiles } from 'services/fileService';
|
2021-10-19 08:19:03 +00:00
|
|
|
import { generateThumbnail } from 'services/upload/thumbnailService';
|
2021-10-08 14:26:49 +00:00
|
|
|
import { getToken } from 'utils/common/key';
|
|
|
|
import { logError } from 'utils/sentry';
|
|
|
|
import { getEndpoint } from 'utils/common/apiUtil';
|
|
|
|
import HTTPService from 'services/HTTPService';
|
|
|
|
import CryptoWorker from 'utils/crypto';
|
|
|
|
import uploadHttpClient from 'services/upload/uploadHttpClient';
|
|
|
|
import { EncryptionResult, UploadURL } from 'services/upload/uploadService';
|
2021-10-18 05:37:59 +00:00
|
|
|
import { SetProgressTracker } from 'components/FixLargeThumbnail';
|
2021-10-08 14:26:49 +00:00
|
|
|
|
|
|
|
const ENDPOINT = getEndpoint();
|
2021-10-19 08:19:03 +00:00
|
|
|
const REPLACE_THUMBNAIL_THRESHOLD = 500 * 1024; // 500KB
|
2021-10-08 14:26:49 +00:00
|
|
|
export async function getLargeThumbnailFiles() {
|
|
|
|
try {
|
|
|
|
const token = getToken();
|
|
|
|
if (!token) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const resp = await HTTPService.get(
|
|
|
|
`${ENDPOINT}/files/large-thumbnails`,
|
|
|
|
{
|
2021-10-19 08:19:03 +00:00
|
|
|
threshold: REPLACE_THUMBNAIL_THRESHOLD,
|
2021-10-08 14:26:49 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
'X-Auth-Token': token,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return resp.data.largeThumbnailFiles as number[];
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'failed to get large thumbnail files');
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|
2021-10-18 08:26:13 +00:00
|
|
|
export async function replaceThumbnail(
|
|
|
|
setProgressTracker: SetProgressTracker,
|
|
|
|
largeThumbnailFileIDs: Set<number>
|
|
|
|
) {
|
2021-10-18 06:19:57 +00:00
|
|
|
let completedWithError = false;
|
2021-10-08 14:26:49 +00:00
|
|
|
try {
|
|
|
|
const token = getToken();
|
|
|
|
const worker = await new CryptoWorker();
|
2021-10-18 05:37:59 +00:00
|
|
|
const files = await getLocalFiles();
|
2021-10-08 14:26:49 +00:00
|
|
|
const largeThumbnailFiles = files.filter((file) =>
|
|
|
|
largeThumbnailFileIDs.has(file.id)
|
|
|
|
);
|
2021-10-18 06:19:57 +00:00
|
|
|
|
2021-10-18 05:37:59 +00:00
|
|
|
if (largeThumbnailFiles.length === 0) {
|
2021-10-18 06:19:57 +00:00
|
|
|
return completedWithError;
|
2021-10-18 05:37:59 +00:00
|
|
|
}
|
|
|
|
setProgressTracker({ current: 0, total: largeThumbnailFiles.length });
|
2021-10-08 14:26:49 +00:00
|
|
|
const uploadURLs: UploadURL[] = [];
|
|
|
|
uploadHttpClient.fetchUploadURLs(
|
|
|
|
largeThumbnailFiles.length,
|
|
|
|
uploadURLs
|
|
|
|
);
|
2021-10-18 05:37:59 +00:00
|
|
|
for (const [idx, file] of largeThumbnailFiles.entries()) {
|
2021-10-18 06:19:57 +00:00
|
|
|
try {
|
|
|
|
setProgressTracker({
|
|
|
|
current: idx,
|
|
|
|
total: largeThumbnailFiles.length,
|
|
|
|
});
|
|
|
|
const originalThumbnail = await downloadManager.getThumbnail(
|
|
|
|
token,
|
|
|
|
file
|
|
|
|
);
|
|
|
|
const dummyImageFile = new globalThis.File(
|
|
|
|
[originalThumbnail],
|
|
|
|
file.metadata.title
|
|
|
|
);
|
|
|
|
const { thumbnail: newThumbnail } = await generateThumbnail(
|
|
|
|
worker,
|
|
|
|
dummyImageFile,
|
|
|
|
FILE_TYPE.IMAGE,
|
|
|
|
false
|
|
|
|
);
|
|
|
|
const newUploadedThumbnail = await uploadThumbnail(
|
|
|
|
worker,
|
|
|
|
file.key,
|
|
|
|
newThumbnail,
|
|
|
|
uploadURLs.pop()
|
|
|
|
);
|
|
|
|
await updateThumbnail(file.id, newUploadedThumbnail);
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'failed to replace a thumbnail');
|
|
|
|
completedWithError = true;
|
|
|
|
}
|
2021-10-08 14:26:49 +00:00
|
|
|
}
|
|
|
|
} catch (e) {
|
2021-10-18 06:19:57 +00:00
|
|
|
logError(e, 'replace Thumbnail function failed');
|
|
|
|
completedWithError = true;
|
2021-10-08 14:26:49 +00:00
|
|
|
}
|
2021-10-18 06:19:57 +00:00
|
|
|
return completedWithError;
|
2021-10-08 14:26:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export async function uploadThumbnail(
|
|
|
|
worker,
|
|
|
|
fileKey: string,
|
|
|
|
updatedThumbnail: Uint8Array,
|
|
|
|
uploadURL: UploadURL
|
|
|
|
): Promise<fileAttribute> {
|
|
|
|
const { file: encryptedThumbnail }: EncryptionResult =
|
|
|
|
await worker.encryptThumbnail(updatedThumbnail, fileKey);
|
|
|
|
|
|
|
|
const thumbnailObjectKey = await uploadHttpClient.putFile(
|
|
|
|
uploadURL,
|
|
|
|
encryptedThumbnail.encryptedData as Uint8Array,
|
|
|
|
() => {}
|
|
|
|
);
|
|
|
|
return {
|
|
|
|
objectKey: thumbnailObjectKey,
|
|
|
|
decryptionHeader: encryptedThumbnail.decryptionHeader,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function updateThumbnail(
|
|
|
|
fileID: number,
|
|
|
|
newThumbnail: fileAttribute
|
|
|
|
) {
|
|
|
|
try {
|
|
|
|
const token = getToken();
|
|
|
|
if (!token) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
await HTTPService.put(
|
|
|
|
`${ENDPOINT}/files/thumbnail`,
|
|
|
|
{
|
|
|
|
fileID: fileID,
|
|
|
|
thumbnail: newThumbnail,
|
|
|
|
},
|
|
|
|
null,
|
|
|
|
{
|
|
|
|
'X-Auth-Token': token,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
logError(e, 'failed to update thumbnail');
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
}
|