Remove unused fix-large-thumbnail feature
This was disabled years ago. Specifically removing this now to reduce the amount of work in removing bootstrap.
This commit is contained in:
parent
e5edeae370
commit
1d02fe4f32
4 changed files with 9 additions and 387 deletions
|
@ -1,235 +0,0 @@
|
|||
import DialogBox from "@ente/shared/components/DialogBox/";
|
||||
import { logError } from "@ente/shared/sentry";
|
||||
import { LS_KEYS, getData, setData } from "@ente/shared/storage/localStorage";
|
||||
import { t } from "i18next";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Button, ProgressBar } from "react-bootstrap";
|
||||
import {
|
||||
getLargeThumbnailFiles,
|
||||
replaceThumbnail,
|
||||
} from "services/migrateThumbnailService";
|
||||
import { ComfySpan } from "./ExportInProgress";
|
||||
|
||||
export type SetProgressTracker = React.Dispatch<
|
||||
React.SetStateAction<{
|
||||
current: number;
|
||||
total: number;
|
||||
}>
|
||||
>;
|
||||
interface Props {
|
||||
isOpen: boolean;
|
||||
show: () => void;
|
||||
hide: () => void;
|
||||
}
|
||||
export enum FIX_STATE {
|
||||
NOT_STARTED,
|
||||
FIX_LATER,
|
||||
NOOP,
|
||||
RUNNING,
|
||||
COMPLETED,
|
||||
COMPLETED_WITH_ERRORS,
|
||||
}
|
||||
function Message({ fixState }: { fixState: FIX_STATE }) {
|
||||
let message = null;
|
||||
switch (fixState) {
|
||||
case FIX_STATE.NOT_STARTED:
|
||||
case FIX_STATE.FIX_LATER:
|
||||
message = t("REPLACE_THUMBNAIL_NOT_STARTED");
|
||||
break;
|
||||
case FIX_STATE.COMPLETED:
|
||||
message = t("REPLACE_THUMBNAIL_COMPLETED");
|
||||
break;
|
||||
case FIX_STATE.NOOP:
|
||||
message = t("REPLACE_THUMBNAIL_NOOP");
|
||||
break;
|
||||
case FIX_STATE.COMPLETED_WITH_ERRORS:
|
||||
message = t("REPLACE_THUMBNAIL_COMPLETED_WITH_ERROR");
|
||||
break;
|
||||
}
|
||||
return message ? (
|
||||
<div style={{ marginBottom: "30px" }}>{message}</div>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
}
|
||||
export default function FixLargeThumbnails(props: Props) {
|
||||
const [fixState, setFixState] = useState(FIX_STATE.NOT_STARTED);
|
||||
const [progressTracker, setProgressTracker] = useState({
|
||||
current: 0,
|
||||
total: 0,
|
||||
});
|
||||
const [largeThumbnailFiles, setLargeThumbnailFiles] = useState<number[]>(
|
||||
[],
|
||||
);
|
||||
|
||||
const init = (): FIX_STATE => {
|
||||
let fixState = getData(LS_KEYS.THUMBNAIL_FIX_STATE)?.state;
|
||||
if (!fixState || fixState === FIX_STATE.RUNNING) {
|
||||
fixState = FIX_STATE.NOT_STARTED;
|
||||
updateFixState(fixState);
|
||||
}
|
||||
if (fixState === FIX_STATE.COMPLETED) {
|
||||
fixState = FIX_STATE.NOOP;
|
||||
updateFixState(fixState);
|
||||
}
|
||||
setFixState(fixState);
|
||||
return fixState;
|
||||
};
|
||||
|
||||
const fetchLargeThumbnail = async () => {
|
||||
const largeThumbnailFiles = (await getLargeThumbnailFiles()) ?? [];
|
||||
setLargeThumbnailFiles(largeThumbnailFiles);
|
||||
return largeThumbnailFiles;
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
const largeThumbnailFiles = await fetchLargeThumbnail();
|
||||
if (
|
||||
fixState === FIX_STATE.NOT_STARTED &&
|
||||
largeThumbnailFiles.length > 0
|
||||
) {
|
||||
props.show();
|
||||
}
|
||||
if (
|
||||
(fixState === FIX_STATE.COMPLETED || fixState === FIX_STATE.NOOP) &&
|
||||
largeThumbnailFiles.length > 0
|
||||
) {
|
||||
updateFixState(FIX_STATE.NOT_STARTED);
|
||||
logError(Error(), "large thumbnail files left after migration");
|
||||
}
|
||||
if (largeThumbnailFiles.length === 0 && fixState !== FIX_STATE.NOOP) {
|
||||
updateFixState(FIX_STATE.NOOP);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
if (props.isOpen && fixState !== FIX_STATE.RUNNING) {
|
||||
main();
|
||||
}
|
||||
}, [props.isOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
const fixState = init();
|
||||
if (fixState === FIX_STATE.NOT_STARTED) {
|
||||
main();
|
||||
}
|
||||
}, []);
|
||||
const startFix = async (newlyFetchedLargeThumbnailFiles?: number[]) => {
|
||||
updateFixState(FIX_STATE.RUNNING);
|
||||
const completedWithError = await replaceThumbnail(
|
||||
setProgressTracker,
|
||||
new Set(
|
||||
newlyFetchedLargeThumbnailFiles ?? largeThumbnailFiles ?? [],
|
||||
),
|
||||
);
|
||||
if (typeof completedWithError !== "undefined") {
|
||||
updateFixState(
|
||||
completedWithError
|
||||
? FIX_STATE.COMPLETED_WITH_ERRORS
|
||||
: FIX_STATE.COMPLETED,
|
||||
);
|
||||
}
|
||||
await fetchLargeThumbnail();
|
||||
};
|
||||
|
||||
const updateFixState = (fixState: FIX_STATE) => {
|
||||
setFixState(fixState);
|
||||
setData(LS_KEYS.THUMBNAIL_FIX_STATE, { state: fixState });
|
||||
};
|
||||
return (
|
||||
<DialogBox
|
||||
open={props.isOpen}
|
||||
onClose={props.hide}
|
||||
attributes={{
|
||||
title: t("COMPRESS_THUMBNAILS"),
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
marginBottom: "20px",
|
||||
padding: "0 5%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<Message fixState={fixState} />
|
||||
|
||||
{fixState === FIX_STATE.RUNNING && (
|
||||
<>
|
||||
<div style={{ marginBottom: "10px" }}>
|
||||
<ComfySpan>
|
||||
{" "}
|
||||
{progressTracker.current} /{" "}
|
||||
{progressTracker.total}{" "}
|
||||
</ComfySpan>{" "}
|
||||
<span style={{ marginLeft: "10px" }}>
|
||||
{" "}
|
||||
{t("THUMBNAIL_REPLACED")}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
marginTop: "10px",
|
||||
marginBottom: "20px",
|
||||
}}
|
||||
>
|
||||
<ProgressBar
|
||||
now={Math.round(
|
||||
(progressTracker.current * 100) /
|
||||
progressTracker.total,
|
||||
)}
|
||||
animated={true}
|
||||
variant="upload-progress-bar"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
justifyContent: "space-around",
|
||||
}}
|
||||
>
|
||||
{fixState === FIX_STATE.NOT_STARTED ||
|
||||
fixState === FIX_STATE.FIX_LATER ? (
|
||||
<Button
|
||||
block
|
||||
variant={"outline-secondary"}
|
||||
onClick={() => {
|
||||
updateFixState(FIX_STATE.FIX_LATER);
|
||||
props.hide();
|
||||
}}
|
||||
>
|
||||
{t("FIX_THUMBNAIL_LATER")}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
block
|
||||
variant={"outline-secondary"}
|
||||
onClick={props.hide}
|
||||
>
|
||||
{t("CLOSE")}
|
||||
</Button>
|
||||
)}
|
||||
{(fixState === FIX_STATE.NOT_STARTED ||
|
||||
fixState === FIX_STATE.FIX_LATER ||
|
||||
fixState === FIX_STATE.COMPLETED_WITH_ERRORS) && (
|
||||
<>
|
||||
<div style={{ width: "30px" }} />
|
||||
|
||||
<Button
|
||||
block
|
||||
variant={"outline-success"}
|
||||
onClick={() => startFix()}
|
||||
>
|
||||
{t("FIX_THUMBNAIL")}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</DialogBox>
|
||||
);
|
||||
}
|
|
@ -1,15 +1,13 @@
|
|||
import { t } from "i18next";
|
||||
import { useContext, useState } from "react";
|
||||
|
||||
// import FixLargeThumbnails from 'components/FixLargeThumbnail';
|
||||
import RecoveryKey from "@ente/shared/components/RecoveryKey";
|
||||
import {
|
||||
ACCOUNTS_PAGES,
|
||||
PHOTOS_PAGES as PAGES,
|
||||
} from "@ente/shared/constants/pages";
|
||||
import TwoFactorModal from "components/TwoFactor/Modal";
|
||||
import { t } from "i18next";
|
||||
import { useRouter } from "next/router";
|
||||
import { AppContext } from "pages/_app";
|
||||
import { useContext, useState } from "react";
|
||||
// import mlIDbStorage from 'utils/storage/mlIDbStorage';
|
||||
import {
|
||||
configurePasskeyRecovery,
|
||||
|
|
|
@ -1,147 +0,0 @@
|
|||
import ComlinkCryptoWorker from "@ente/shared/crypto";
|
||||
import { DedicatedCryptoWorker } from "@ente/shared/crypto/internal/crypto.worker";
|
||||
import HTTPService from "@ente/shared/network/HTTPService";
|
||||
import { getEndpoint } from "@ente/shared/network/api";
|
||||
import { logError } from "@ente/shared/sentry";
|
||||
import { getToken } from "@ente/shared/storage/localStorage/helpers";
|
||||
import { Remote } from "comlink";
|
||||
import { SetProgressTracker } from "components/FixLargeThumbnail";
|
||||
import downloadManager from "services/download";
|
||||
import { getLocalFiles } from "services/fileService";
|
||||
import { getFileType } from "services/typeDetectionService";
|
||||
import { generateThumbnail } from "services/upload/thumbnailService";
|
||||
import uploadHttpClient from "services/upload/uploadHttpClient";
|
||||
import { S3FileAttributes } from "types/file";
|
||||
import { UploadURL } from "types/upload";
|
||||
import { getLocalTrashedFiles } from "./trashService";
|
||||
|
||||
const ENDPOINT = getEndpoint();
|
||||
const REPLACE_THUMBNAIL_THRESHOLD = 500 * 1024; // 500KB
|
||||
export async function getLargeThumbnailFiles() {
|
||||
try {
|
||||
const token = getToken();
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
const resp = await HTTPService.get(
|
||||
`${ENDPOINT}/files/large-thumbnails`,
|
||||
{
|
||||
threshold: REPLACE_THUMBNAIL_THRESHOLD,
|
||||
},
|
||||
{
|
||||
"X-Auth-Token": token,
|
||||
},
|
||||
);
|
||||
return resp.data.largeThumbnailFiles as number[];
|
||||
} catch (e) {
|
||||
logError(e, "failed to get large thumbnail files");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
export async function replaceThumbnail(
|
||||
setProgressTracker: SetProgressTracker,
|
||||
largeThumbnailFileIDs: Set<number>,
|
||||
) {
|
||||
let completedWithError = false;
|
||||
try {
|
||||
const cryptoWorker = await ComlinkCryptoWorker.getInstance();
|
||||
const files = await getLocalFiles();
|
||||
const trashFiles = await getLocalTrashedFiles();
|
||||
const largeThumbnailFiles = [...files, ...trashFiles].filter((file) =>
|
||||
largeThumbnailFileIDs.has(file.id),
|
||||
);
|
||||
if (largeThumbnailFileIDs.size !== largeThumbnailFiles.length) {
|
||||
logError(Error(), "all large thumbnail files not found locally");
|
||||
}
|
||||
if (largeThumbnailFiles.length === 0) {
|
||||
return completedWithError;
|
||||
}
|
||||
setProgressTracker({ current: 0, total: largeThumbnailFiles.length });
|
||||
const uploadURLs: UploadURL[] = [];
|
||||
await uploadHttpClient.fetchUploadURLs(
|
||||
largeThumbnailFiles.length,
|
||||
uploadURLs,
|
||||
);
|
||||
for (const [idx, file] of largeThumbnailFiles.entries()) {
|
||||
try {
|
||||
setProgressTracker({
|
||||
current: idx,
|
||||
total: largeThumbnailFiles.length,
|
||||
});
|
||||
const originalThumbnail =
|
||||
await downloadManager.getThumbnail(file);
|
||||
const dummyImageFile = new File(
|
||||
[originalThumbnail],
|
||||
file.metadata.title,
|
||||
);
|
||||
const fileTypeInfo = await getFileType(dummyImageFile);
|
||||
const { thumbnail: newThumbnail } = await generateThumbnail(
|
||||
dummyImageFile,
|
||||
fileTypeInfo,
|
||||
);
|
||||
const newUploadedThumbnail = await uploadThumbnail(
|
||||
cryptoWorker,
|
||||
file.key,
|
||||
newThumbnail,
|
||||
uploadURLs.pop(),
|
||||
);
|
||||
await updateThumbnail(file.id, newUploadedThumbnail);
|
||||
} catch (e) {
|
||||
logError(e, "failed to replace a thumbnail");
|
||||
completedWithError = true;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
logError(e, "replace Thumbnail function failed");
|
||||
completedWithError = true;
|
||||
}
|
||||
return completedWithError;
|
||||
}
|
||||
|
||||
export async function uploadThumbnail(
|
||||
worker: Remote<DedicatedCryptoWorker>,
|
||||
fileKey: string,
|
||||
updatedThumbnail: Uint8Array,
|
||||
uploadURL: UploadURL,
|
||||
): Promise<S3FileAttributes> {
|
||||
const { file: encryptedThumbnail } = await worker.encryptThumbnail(
|
||||
updatedThumbnail,
|
||||
fileKey,
|
||||
);
|
||||
const thumbnailObjectKey = await uploadHttpClient.putFile(
|
||||
uploadURL,
|
||||
encryptedThumbnail.encryptedData,
|
||||
() => {},
|
||||
);
|
||||
|
||||
return {
|
||||
objectKey: thumbnailObjectKey,
|
||||
decryptionHeader: encryptedThumbnail.decryptionHeader,
|
||||
};
|
||||
}
|
||||
|
||||
export async function updateThumbnail(
|
||||
fileID: number,
|
||||
newThumbnail: S3FileAttributes,
|
||||
) {
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import { logError } from "@ente/shared/sentry";
|
||||
import { FIX_OPTIONS } from "components/FixCreationTime";
|
||||
import { SetProgressTracker } from "components/FixLargeThumbnail";
|
||||
import { EnteFile } from "types/file";
|
||||
import {
|
||||
changeFileCreationTime,
|
||||
|
@ -21,6 +20,13 @@ const EXIF_TIME_TAGS = [
|
|||
"MetadataDate",
|
||||
];
|
||||
|
||||
export type SetProgressTracker = React.Dispatch<
|
||||
React.SetStateAction<{
|
||||
current: number;
|
||||
total: number;
|
||||
}>
|
||||
>;
|
||||
|
||||
export async function updateCreationTimeWithExif(
|
||||
filesToBeUpdated: EnteFile[],
|
||||
fixOption: FIX_OPTIONS,
|
||||
|
|
Loading…
Reference in a new issue