Ref
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { UPLOAD_STAGES } from "@/new/photos/services/upload/types";
|
||||
import { type UploadPhase } from "@/new/photos/services/upload/types";
|
||||
import { createContext } from "react";
|
||||
import type {
|
||||
InProgressUpload,
|
||||
@@ -11,7 +11,7 @@ interface UploadProgressContextType {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
uploadCounter: UploadCounter;
|
||||
uploadStage: UPLOAD_STAGES;
|
||||
uploadPhase: UploadPhase;
|
||||
percentComplete: number;
|
||||
retryFailed: () => void;
|
||||
inProgressUploads: InProgressUpload[];
|
||||
@@ -25,7 +25,7 @@ const defaultUploadProgressContext: UploadProgressContextType = {
|
||||
open: null,
|
||||
onClose: () => null,
|
||||
uploadCounter: null,
|
||||
uploadStage: null,
|
||||
uploadPhase: undefined,
|
||||
percentComplete: null,
|
||||
retryFailed: () => null,
|
||||
inProgressUploads: null,
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
UPLOAD_RESULT,
|
||||
UPLOAD_STAGES,
|
||||
} from "@/new/photos/services/upload/types";
|
||||
import { UPLOAD_RESULT } from "@/new/photos/services/upload/types";
|
||||
import { Dialog, DialogContent, type DialogProps } from "@mui/material";
|
||||
import { t } from "i18next";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
@@ -14,7 +11,7 @@ import { ResultSection } from "./resultSection";
|
||||
import { NotUploadSectionHeader } from "./styledComponents";
|
||||
|
||||
export function UploadProgressDialog() {
|
||||
const { open, onClose, uploadStage, finishedUploads } = useContext(
|
||||
const { open, onClose, uploadPhase, finishedUploads } = useContext(
|
||||
UploadProgressContext,
|
||||
);
|
||||
|
||||
@@ -43,16 +40,13 @@ export function UploadProgressDialog() {
|
||||
return (
|
||||
<Dialog open={open} onClose={handleClose} maxWidth="xs" fullWidth>
|
||||
<UploadProgressHeader />
|
||||
{(uploadStage === UPLOAD_STAGES.UPLOADING ||
|
||||
uploadStage === UPLOAD_STAGES.FINISH ||
|
||||
uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA) && (
|
||||
{(uploadPhase == "extractingMetadata" ||
|
||||
uploadPhase == "uploading" ||
|
||||
uploadPhase == "done") && (
|
||||
<DialogContent sx={{ "&&&": { px: 0 } }}>
|
||||
{(uploadStage === UPLOAD_STAGES.UPLOADING ||
|
||||
uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA) && (
|
||||
<InProgressSection />
|
||||
)}
|
||||
{(uploadStage === UPLOAD_STAGES.UPLOADING ||
|
||||
uploadStage === UPLOAD_STAGES.FINISH) && (
|
||||
{(uploadPhase == "extractingMetadata" ||
|
||||
uploadPhase === "uploading") && <InProgressSection />}
|
||||
{(uploadPhase == "uploading" || uploadPhase == "done") && (
|
||||
<>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.UPLOADED}
|
||||
@@ -69,12 +63,11 @@ export function UploadProgressDialog() {
|
||||
"THUMBNAIL_GENERATION_FAILED_INFO",
|
||||
)}
|
||||
/>
|
||||
{uploadStage === UPLOAD_STAGES.FINISH &&
|
||||
hasUnUploadedFiles && (
|
||||
<NotUploadSectionHeader>
|
||||
{t("FILE_NOT_UPLOADED_LIST")}
|
||||
</NotUploadSectionHeader>
|
||||
)}
|
||||
{uploadPhase == "done" && hasUnUploadedFiles && (
|
||||
<NotUploadSectionHeader>
|
||||
{t("FILE_NOT_UPLOADED_LIST")}
|
||||
</NotUploadSectionHeader>
|
||||
)}
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.BLOCKED}
|
||||
sectionTitle={t("BLOCKED_UPLOADS")}
|
||||
@@ -86,7 +79,7 @@ export function UploadProgressDialog() {
|
||||
uploadResult={UPLOAD_RESULT.FAILED}
|
||||
sectionTitle={t("FAILED_UPLOADS")}
|
||||
sectionInfo={
|
||||
uploadStage === UPLOAD_STAGES.FINISH
|
||||
uploadPhase == "done"
|
||||
? undefined
|
||||
: t("failed_uploads_hint")
|
||||
}
|
||||
@@ -121,7 +114,7 @@ export function UploadProgressDialog() {
|
||||
)}
|
||||
</DialogContent>
|
||||
)}
|
||||
{uploadStage === UPLOAD_STAGES.FINISH && <UploadProgressFooter />}
|
||||
{uploadPhase == "done" && <UploadProgressFooter />}
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,20 +1,17 @@
|
||||
import {
|
||||
UPLOAD_RESULT,
|
||||
UPLOAD_STAGES,
|
||||
} from "@/new/photos/services/upload/types";
|
||||
import { UPLOAD_RESULT } from "@/new/photos/services/upload/types";
|
||||
import { Button, DialogActions } from "@mui/material";
|
||||
import { t } from "i18next";
|
||||
import { useContext } from "react";
|
||||
import UploadProgressContext from "./context";
|
||||
|
||||
export function UploadProgressFooter() {
|
||||
const { uploadStage, finishedUploads, retryFailed, onClose } = useContext(
|
||||
const { uploadPhase, finishedUploads, retryFailed, onClose } = useContext(
|
||||
UploadProgressContext,
|
||||
);
|
||||
|
||||
return (
|
||||
<DialogActions>
|
||||
{uploadStage === UPLOAD_STAGES.FINISH &&
|
||||
{uploadPhase == "done" &&
|
||||
(finishedUploads?.get(UPLOAD_RESULT.FAILED)?.length > 0 ||
|
||||
finishedUploads?.get(UPLOAD_RESULT.BLOCKED)?.length > 0 ? (
|
||||
<Button variant="contained" fullWidth onClick={retryFailed}>
|
||||
|
||||
@@ -11,11 +11,10 @@ import {
|
||||
} from "./section";
|
||||
import { InProgressItemContainer } from "./styledComponents";
|
||||
|
||||
import { UPLOAD_STAGES } from "@/new/photos/services/upload/types";
|
||||
import { CaptionedText } from "components/CaptionedText";
|
||||
|
||||
export const InProgressSection = () => {
|
||||
const { inProgressUploads, hasLivePhotos, uploadFileNames, uploadStage } =
|
||||
const { inProgressUploads, hasLivePhotos, uploadFileNames, uploadPhase } =
|
||||
useContext(UploadProgressContext);
|
||||
const fileList = inProgressUploads ?? [];
|
||||
|
||||
@@ -23,7 +22,7 @@ export const InProgressSection = () => {
|
||||
return (
|
||||
<InProgressItemContainer key={localFileID}>
|
||||
<span>{uploadFileNames.get(localFileID)}</span>
|
||||
{uploadStage === UPLOAD_STAGES.UPLOADING && (
|
||||
{uploadPhase == "uploading" && (
|
||||
<>
|
||||
{" "}
|
||||
<span className="separator">{`-`}</span>
|
||||
@@ -47,7 +46,7 @@ export const InProgressSection = () => {
|
||||
<UploadProgressSectionTitle expandIcon={<ExpandMoreIcon />}>
|
||||
<CaptionedText
|
||||
mainText={
|
||||
uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA
|
||||
uploadPhase == "extractingMetadata"
|
||||
? t("INPROGRESS_METADATA_EXTRACTION")
|
||||
: t("INPROGRESS_UPLOADS")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { UPLOAD_STAGES } from "@/new/photos/services/upload/types";
|
||||
import { type UploadPhase } from "@/new/photos/services/upload/types";
|
||||
import { useAppContext } from "@/new/photos/types/context";
|
||||
import { t } from "i18next";
|
||||
import { useEffect, useState } from "react";
|
||||
@@ -16,7 +16,7 @@ interface Props {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
uploadCounter: UploadCounter;
|
||||
uploadStage: UPLOAD_STAGES;
|
||||
uploadPhase: UploadPhase;
|
||||
percentComplete: number;
|
||||
retryFailed: () => void;
|
||||
inProgressUploads: InProgressUpload[];
|
||||
@@ -29,7 +29,7 @@ interface Props {
|
||||
export default function UploadProgress({
|
||||
open,
|
||||
uploadCounter,
|
||||
uploadStage,
|
||||
uploadPhase,
|
||||
percentComplete,
|
||||
retryFailed,
|
||||
uploadFileNames,
|
||||
@@ -62,7 +62,7 @@ export default function UploadProgress({
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
if (uploadStage !== UPLOAD_STAGES.FINISH) {
|
||||
if (uploadPhase != "done") {
|
||||
confirmCancelUpload();
|
||||
} else {
|
||||
props.onClose();
|
||||
@@ -79,7 +79,7 @@ export default function UploadProgress({
|
||||
open,
|
||||
onClose,
|
||||
uploadCounter,
|
||||
uploadStage,
|
||||
uploadPhase,
|
||||
percentComplete,
|
||||
retryFailed,
|
||||
inProgressUploads,
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { UPLOAD_STAGES } from "@/new/photos/services/upload/types";
|
||||
import { Box, Divider, LinearProgress } from "@mui/material";
|
||||
import { useContext } from "react";
|
||||
import UploadProgressContext from "./context";
|
||||
|
||||
export function UploadProgressBar() {
|
||||
const { uploadStage, percentComplete } = useContext(UploadProgressContext);
|
||||
const { uploadPhase, percentComplete } = useContext(UploadProgressContext);
|
||||
return (
|
||||
<Box>
|
||||
{(uploadStage === UPLOAD_STAGES.READING_GOOGLE_METADATA_FILES ||
|
||||
uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA ||
|
||||
uploadStage === UPLOAD_STAGES.UPLOADING) && (
|
||||
{(uploadPhase == "readingMetadata" ||
|
||||
uploadPhase == "extractingMetadata" ||
|
||||
uploadPhase == "uploading") && (
|
||||
<>
|
||||
<LinearProgress
|
||||
sx={{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { FilledIconButton } from "@/new/photos/components/mui";
|
||||
import { UPLOAD_STAGES } from "@/new/photos/services/upload/types";
|
||||
import { type UploadPhase } from "@/new/photos/services/upload/types";
|
||||
import { SpaceBetweenFlex } from "@ente/shared/components/Container";
|
||||
import Close from "@mui/icons-material/Close";
|
||||
import UnfoldLessIcon from "@mui/icons-material/UnfoldLess";
|
||||
@@ -7,6 +7,7 @@ import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore";
|
||||
import { Box, DialogTitle, Stack, Typography } from "@mui/material";
|
||||
import { t } from "i18next";
|
||||
import { useContext } from "react";
|
||||
import type { UploadCounter } from "services/upload/uploadManager";
|
||||
import UploadProgressContext from "./context";
|
||||
|
||||
const UploadProgressTitleText = ({ expanded }) => {
|
||||
@@ -18,7 +19,7 @@ const UploadProgressTitleText = ({ expanded }) => {
|
||||
};
|
||||
|
||||
function UploadProgressSubtitleText() {
|
||||
const { uploadStage, uploadCounter } = useContext(UploadProgressContext);
|
||||
const { uploadPhase, uploadCounter } = useContext(UploadProgressContext);
|
||||
|
||||
return (
|
||||
<Typography
|
||||
@@ -27,15 +28,31 @@ function UploadProgressSubtitleText() {
|
||||
color="text.muted"
|
||||
marginTop={"4px"}
|
||||
>
|
||||
{uploadStage === UPLOAD_STAGES.UPLOADING
|
||||
? t(`UPLOAD_STAGE_MESSAGE.${uploadStage}`, { uploadCounter })
|
||||
: uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA
|
||||
? t(`UPLOAD_STAGE_MESSAGE.${uploadStage}`, { uploadCounter })
|
||||
: t(`UPLOAD_STAGE_MESSAGE.${uploadStage}`)}
|
||||
{subtitleText(uploadPhase, uploadCounter)}
|
||||
</Typography>
|
||||
);
|
||||
}
|
||||
|
||||
const subtitleText = (
|
||||
uploadPhase: UploadPhase,
|
||||
uploadCounter: UploadCounter,
|
||||
) => {
|
||||
switch (uploadPhase) {
|
||||
case "preparing":
|
||||
return t("UPLOAD_STAGE_MESSAGE.0");
|
||||
case "readingMetadata":
|
||||
return t("UPLOAD_STAGE_MESSAGE.1");
|
||||
case "extractingMetadata":
|
||||
return t("UPLOAD_STAGE_MESSAGE.2", { uploadCounter });
|
||||
case "uploading":
|
||||
return t("UPLOAD_STAGE_MESSAGE.3", { uploadCounter });
|
||||
case "cancelling":
|
||||
return t("UPLOAD_STAGE_MESSAGE.4");
|
||||
case "done":
|
||||
return t("UPLOAD_STAGE_MESSAGE.5");
|
||||
}
|
||||
};
|
||||
|
||||
export function UploadProgressTitle() {
|
||||
const { setExpanded, onClose, expanded } = useContext(
|
||||
UploadProgressContext,
|
||||
|
||||
@@ -12,8 +12,8 @@ import { exportMetadataDirectoryName } from "@/new/photos/services/export";
|
||||
import type {
|
||||
FileAndPath,
|
||||
UploadItem,
|
||||
UploadPhase,
|
||||
} from "@/new/photos/services/upload/types";
|
||||
import { UPLOAD_STAGES } from "@/new/photos/services/upload/types";
|
||||
import { redirectToCustomerPortal } from "@/new/photos/services/user-details";
|
||||
import { useAppContext } from "@/new/photos/types/context";
|
||||
import { NotificationAttributes } from "@/new/photos/types/notification";
|
||||
@@ -121,9 +121,7 @@ export default function Uploader({
|
||||
);
|
||||
|
||||
const [uploadProgressView, setUploadProgressView] = useState(false);
|
||||
const [uploadStage, setUploadStage] = useState<UPLOAD_STAGES>(
|
||||
UPLOAD_STAGES.START,
|
||||
);
|
||||
const [uploadPhase, setUploadPhase] = useState<UploadPhase>("preparing");
|
||||
const [uploadFileNames, setUploadFileNames] = useState<UploadFileNames>();
|
||||
const [uploadCounter, setUploadCounter] = useState<UploadCounter>({
|
||||
finished: 0,
|
||||
@@ -245,7 +243,7 @@ export default function Uploader({
|
||||
setUploadCounter,
|
||||
setInProgressUploads,
|
||||
setFinishedUploads,
|
||||
setUploadStage,
|
||||
setUploadPhase,
|
||||
setUploadFilenames: setUploadFileNames,
|
||||
setHasLivePhotos,
|
||||
setUploadProgressView,
|
||||
@@ -486,7 +484,7 @@ export default function Uploader({
|
||||
const preCollectionCreationAction = async () => {
|
||||
props.onCloseCollectionSelector?.();
|
||||
props.setShouldDisableDropzone(!uploadManager.shouldAllowNewUpload());
|
||||
setUploadStage(UPLOAD_STAGES.START);
|
||||
setUploadPhase("preparing");
|
||||
setUploadProgressView(true);
|
||||
};
|
||||
|
||||
@@ -802,7 +800,7 @@ export default function Uploader({
|
||||
percentComplete={percentComplete}
|
||||
uploadFileNames={uploadFileNames}
|
||||
uploadCounter={uploadCounter}
|
||||
uploadStage={uploadStage}
|
||||
uploadPhase={uploadPhase}
|
||||
inProgressUploads={inProgressUploads}
|
||||
hasLivePhotos={hasLivePhotos}
|
||||
retryFailed={retryFailed}
|
||||
|
||||
@@ -15,7 +15,7 @@ import type { UploadItem } from "@/new/photos/services/upload/types";
|
||||
import {
|
||||
RANDOM_PERCENTAGE_PROGRESS_FOR_PUT,
|
||||
UPLOAD_RESULT,
|
||||
UPLOAD_STAGES,
|
||||
type UploadPhase,
|
||||
} from "@/new/photos/services/upload/types";
|
||||
import { ensure } from "@/utils/ensure";
|
||||
import { wait } from "@/utils/promise";
|
||||
@@ -70,7 +70,7 @@ export type SegregatedFinishedUploads = Map<UPLOAD_RESULT, FileID[]>;
|
||||
export interface ProgressUpdater {
|
||||
setPercentComplete: React.Dispatch<React.SetStateAction<number>>;
|
||||
setUploadCounter: React.Dispatch<React.SetStateAction<UploadCounter>>;
|
||||
setUploadStage: React.Dispatch<React.SetStateAction<UPLOAD_STAGES>>;
|
||||
setUploadPhase: (phase: UploadPhase) => void;
|
||||
setInProgressUploads: React.Dispatch<
|
||||
React.SetStateAction<InProgressUpload[]>
|
||||
>;
|
||||
@@ -132,7 +132,7 @@ class UIService {
|
||||
private progressUpdater: ProgressUpdater;
|
||||
|
||||
// UPLOAD LEVEL STATES
|
||||
private uploadStage: UPLOAD_STAGES = UPLOAD_STAGES.START;
|
||||
private uploadPhase: UploadPhase = "preparing";
|
||||
private filenames: Map<number, string> = new Map();
|
||||
private hasLivePhoto: boolean = false;
|
||||
private uploadProgressView: boolean = false;
|
||||
@@ -146,7 +146,7 @@ class UIService {
|
||||
|
||||
init(progressUpdater: ProgressUpdater) {
|
||||
this.progressUpdater = progressUpdater;
|
||||
this.progressUpdater.setUploadStage(this.uploadStage);
|
||||
this.progressUpdater.setUploadPhase(this.uploadPhase);
|
||||
this.progressUpdater.setUploadFilenames(this.filenames);
|
||||
this.progressUpdater.setHasLivePhotos(this.hasLivePhoto);
|
||||
this.progressUpdater.setUploadProgressView(this.uploadProgressView);
|
||||
@@ -184,9 +184,9 @@ class UIService {
|
||||
this.updateProgressBarUI();
|
||||
}
|
||||
|
||||
setUploadStage(stage: UPLOAD_STAGES) {
|
||||
this.uploadStage = stage;
|
||||
this.progressUpdater.setUploadStage(stage);
|
||||
setUploadPhase(phase: UploadPhase) {
|
||||
this.uploadPhase = phase;
|
||||
this.progressUpdater.setUploadPhase(phase);
|
||||
}
|
||||
|
||||
setFiles(files: { localID: number; fileName: string }[]) {
|
||||
@@ -363,7 +363,7 @@ class UploadManager {
|
||||
this.resetState();
|
||||
this.uiService.reset();
|
||||
uploadCancelService.reset();
|
||||
this.uiService.setUploadStage(UPLOAD_STAGES.START);
|
||||
this.uiService.setUploadPhase("preparing");
|
||||
}
|
||||
|
||||
showUploadProgressDialog() {
|
||||
@@ -411,10 +411,7 @@ class UploadManager {
|
||||
splitMetadataAndMediaItems(namedItems);
|
||||
|
||||
if (metadataItems.length) {
|
||||
this.uiService.setUploadStage(
|
||||
UPLOAD_STAGES.READING_GOOGLE_METADATA_FILES,
|
||||
);
|
||||
|
||||
this.uiService.setUploadPhase("readingMetadata");
|
||||
await this.parseMetadataJSONFiles(metadataItems);
|
||||
}
|
||||
|
||||
@@ -442,7 +439,7 @@ class UploadManager {
|
||||
throw e;
|
||||
}
|
||||
} finally {
|
||||
this.uiService.setUploadStage(UPLOAD_STAGES.FINISH);
|
||||
this.uiService.setUploadPhase("done");
|
||||
void globalThis.electron?.clearPendingUploads();
|
||||
for (let i = 0; i < maxConcurrentUploads; i++) {
|
||||
this.comlinkCryptoWorkers[i]?.terminate();
|
||||
@@ -499,7 +496,7 @@ class UploadManager {
|
||||
this.itemsToBeUploaded = [...this.itemsToBeUploaded, ...mediaItems];
|
||||
this.uiService.reset(mediaItems.length);
|
||||
await UploadService.setFileCount(mediaItems.length);
|
||||
this.uiService.setUploadStage(UPLOAD_STAGES.UPLOADING);
|
||||
this.uiService.setUploadPhase("uploading");
|
||||
|
||||
const uploadProcesses = [];
|
||||
for (
|
||||
@@ -653,7 +650,7 @@ class UploadManager {
|
||||
|
||||
public cancelRunningUpload() {
|
||||
log.info("User cancelled running upload");
|
||||
this.uiService.setUploadStage(UPLOAD_STAGES.CANCELLING);
|
||||
this.uiService.setUploadPhase("cancelling");
|
||||
uploadCancelService.requestUploadCancelation();
|
||||
}
|
||||
|
||||
|
||||
@@ -58,14 +58,13 @@ export const toDataOrPathOrZipEntry = (desktopUploadItem: DesktopUploadItem) =>
|
||||
|
||||
export const RANDOM_PERCENTAGE_PROGRESS_FOR_PUT = () => 90 + 10 * Math.random();
|
||||
|
||||
export enum UPLOAD_STAGES {
|
||||
START,
|
||||
READING_GOOGLE_METADATA_FILES,
|
||||
EXTRACTING_METADATA,
|
||||
UPLOADING,
|
||||
CANCELLING,
|
||||
FINISH,
|
||||
}
|
||||
export type UploadPhase =
|
||||
| "preparing"
|
||||
| "readingMetadata"
|
||||
| "extractingMetadata"
|
||||
| "uploading"
|
||||
| "cancelling"
|
||||
| "done";
|
||||
|
||||
export enum UPLOAD_RESULT {
|
||||
FAILED,
|
||||
|
||||
Reference in New Issue
Block a user