[web] General refactoring - Uploads (#4017)
This commit is contained in:
@@ -86,7 +86,7 @@ export const CollectionShare: React.FC<CollectionShareProps> = ({
|
||||
props.onClose();
|
||||
};
|
||||
const handleDrawerClose: DialogProps["onClose"] = (_, reason) => {
|
||||
if (reason === "backdropClick") {
|
||||
if (reason == "backdropClick") {
|
||||
handleRootClose();
|
||||
} else {
|
||||
props.onClose();
|
||||
@@ -539,7 +539,7 @@ const AddParticipant: React.FC<AddParticipantProps> = ({
|
||||
};
|
||||
|
||||
const handleDrawerClose: DialogProps["onClose"] = (_, reason) => {
|
||||
if (reason === "backdropClick") {
|
||||
if (reason == "backdropClick") {
|
||||
handleRootClose();
|
||||
} else {
|
||||
onClose();
|
||||
@@ -853,7 +853,7 @@ const ManageEmailShare: React.FC<ManageEmailShareProps> = ({
|
||||
onRootClose();
|
||||
};
|
||||
const handleDrawerClose: DialogProps["onClose"] = (_, reason) => {
|
||||
if (reason === "backdropClick") {
|
||||
if (reason == "backdropClick") {
|
||||
handleRootClose();
|
||||
} else {
|
||||
onClose();
|
||||
@@ -1037,7 +1037,7 @@ const ManageParticipant: React.FC<ManageParticipantProps> = ({
|
||||
const galleryContext = useContext(GalleryContext);
|
||||
|
||||
const handleDrawerClose: DialogProps["onClose"] = (_, reason) => {
|
||||
if (reason === "backdropClick") {
|
||||
if (reason == "backdropClick") {
|
||||
onRootClose();
|
||||
} else {
|
||||
onClose();
|
||||
@@ -1356,7 +1356,7 @@ const ManagePublicShareOptions: React.FC<ManagePublicShareOptionsProps> = ({
|
||||
publicShareUrl,
|
||||
}) => {
|
||||
const handleDrawerClose: DialogProps["onClose"] = (_, reason) => {
|
||||
if (reason === "backdropClick") {
|
||||
if (reason == "backdropClick") {
|
||||
onRootClose();
|
||||
} else {
|
||||
onClose();
|
||||
@@ -1552,7 +1552,7 @@ const ManageLinkExpiry: React.FC<ManageLinkExpiryProps> = ({
|
||||
};
|
||||
|
||||
const handleDrawerClose: DialogProps["onClose"] = (_, reason) => {
|
||||
if (reason === "backdropClick") {
|
||||
if (reason == "backdropClick") {
|
||||
onRootClose();
|
||||
} else {
|
||||
closeShareExpiryOptionsModalView();
|
||||
@@ -1684,7 +1684,7 @@ const ManageDeviceLimit: React.FC<ManageDeviceLimitProps> = ({
|
||||
};
|
||||
|
||||
const handleDrawerClose: DialogProps["onClose"] = (_, reason) => {
|
||||
if (reason === "backdropClick") {
|
||||
if (reason == "backdropClick") {
|
||||
onRootClose();
|
||||
} else {
|
||||
closeDeviceLimitChangeModal();
|
||||
@@ -1897,7 +1897,7 @@ function PublicLinkSetPassword({
|
||||
fullWidth
|
||||
>
|
||||
<Stack spacing={3} p={1.5}>
|
||||
<Typography variant="h3" px={1} py={0.5} fontWeight={"bold"}>
|
||||
<Typography variant="h3" fontWeight={"bold"} px={1} py={0.5}>
|
||||
{t("password_lock")}
|
||||
</Typography>
|
||||
<SingleInputForm
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { EnteSwitch } from "@/base/components/EnteSwitch";
|
||||
import type { ModalVisibilityProps } from "@/base/components/utils/modal";
|
||||
import { ensureElectron } from "@/base/electron";
|
||||
import log from "@/base/log";
|
||||
import { EnteFile } from "@/media/file";
|
||||
import { DialogCloseIconButton } from "@/new/photos/components/mui/Dialog";
|
||||
import { useAppContext } from "@/new/photos/types/context";
|
||||
import ChangeDirectoryOption from "@ente/shared/components/ChangeDirectoryOption";
|
||||
import {
|
||||
@@ -9,13 +11,13 @@ import {
|
||||
VerticallyCenteredFlex,
|
||||
} from "@ente/shared/components/Container";
|
||||
import LinkButton from "@ente/shared/components/LinkButton";
|
||||
import DialogTitleWithCloseButton from "@ente/shared/components/TitleWithCloseButton";
|
||||
import { CustomError } from "@ente/shared/error";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Divider,
|
||||
Tooltip,
|
||||
Typography,
|
||||
@@ -35,13 +37,15 @@ import ExportFinished from "./ExportFinished";
|
||||
import ExportInProgress from "./ExportInProgress";
|
||||
import ExportInit from "./ExportInit";
|
||||
|
||||
interface ExportModalProps {
|
||||
show: boolean;
|
||||
onHide: () => void;
|
||||
type ExportProps = ModalVisibilityProps & {
|
||||
collectionNameMap: Map<number, string>;
|
||||
}
|
||||
};
|
||||
|
||||
export default function ExportModal(props: ExportModalProps) {
|
||||
export const Export: React.FC<ExportProps> = ({
|
||||
open,
|
||||
onClose,
|
||||
collectionNameMap,
|
||||
}) => {
|
||||
const { showMiniDialog } = useAppContext();
|
||||
const [exportStage, setExportStage] = useState(ExportStage.INIT);
|
||||
const [exportFolder, setExportFolder] = useState("");
|
||||
@@ -79,11 +83,11 @@ export default function ExportModal(props: ExportModalProps) {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!props.show) {
|
||||
if (!open) {
|
||||
return;
|
||||
}
|
||||
void syncExportRecord(exportFolder);
|
||||
}, [props.show]);
|
||||
}, [open]);
|
||||
|
||||
// ======================
|
||||
// HELPER FUNCTIONS
|
||||
@@ -166,15 +170,14 @@ export default function ExportModal(props: ExportModalProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={props.show}
|
||||
onClose={props.onHide}
|
||||
maxWidth="xs"
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitleWithCloseButton onClose={props.onHide}>
|
||||
{t("export_data")}
|
||||
</DialogTitleWithCloseButton>
|
||||
<Dialog {...{ open, onClose }} maxWidth="xs" fullWidth>
|
||||
<SpaceBetweenFlex sx={{ p: "12px 4px 0px 0px" }}>
|
||||
<DialogTitle variant="h3" fontWeight={"bold"}>
|
||||
{t("export_data")}
|
||||
</DialogTitle>
|
||||
<DialogCloseIconButton {...{ onClose }} />
|
||||
</SpaceBetweenFlex>
|
||||
|
||||
<DialogContent>
|
||||
<ExportDirectory
|
||||
exportFolder={exportFolder}
|
||||
@@ -191,15 +194,15 @@ export default function ExportModal(props: ExportModalProps) {
|
||||
exportStage={exportStage}
|
||||
startExport={startExport}
|
||||
stopExport={stopExport}
|
||||
onHide={props.onHide}
|
||||
onHide={onClose}
|
||||
lastExportTime={lastExportTime}
|
||||
exportProgress={exportProgress}
|
||||
pendingExports={pendingExports}
|
||||
collectionNameMap={props.collectionNameMap}
|
||||
collectionNameMap={collectionNameMap}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
function ExportDirectory({ exportFolder, changeExportDirectory, exportStage }) {
|
||||
return (
|
||||
@@ -84,10 +84,11 @@ export const FixCreationTime: React.FC<FixCreationTimeProps> = ({
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogTitle sx={{ marginBlockStart: "4px" }}>{title}</DialogTitle>
|
||||
<DialogContent
|
||||
style={{
|
||||
minWidth: "310px",
|
||||
paddingBlockStart: "6px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
...(step == "running" ? { alignItems: "center" } : {}),
|
||||
@@ -235,7 +236,7 @@ const Footer: React.FC<FooterProps> = ({ step, onSubmit, onClose }) =>
|
||||
style={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
marginTop: "30px",
|
||||
marginTop: "24px",
|
||||
justifyContent: "space-around",
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { openAccountsManagePasskeysPage } from "@/accounts/services/passkey";
|
||||
import { isDesktop } from "@/base/app";
|
||||
import { EnteLogo } from "@/base/components/EnteLogo";
|
||||
import { ActivityIndicator } from "@/base/components/mui/ActivityIndicator";
|
||||
import { SpaceBetweenFlex } from "@/base/components/mui/Container";
|
||||
import { SidebarDrawer } from "@/base/components/mui/SidebarDrawer";
|
||||
import { useModalVisibility } from "@/base/components/utils/modal";
|
||||
import { useIsSmallWidth } from "@/base/hooks";
|
||||
@@ -10,6 +11,7 @@ import log from "@/base/log";
|
||||
import { savedLogs } from "@/base/log-web";
|
||||
import { customAPIHost } from "@/base/origins";
|
||||
import { downloadString } from "@/base/utils/web";
|
||||
import { DialogCloseIconButton } from "@/new/photos/components/mui/Dialog";
|
||||
import { TwoFactorSettings } from "@/new/photos/components/sidebar/TwoFactorSettings";
|
||||
import { downloadAppDialogAttributes } from "@/new/photos/components/utils/download";
|
||||
import { useUserDetailsSnapshot } from "@/new/photos/components/utils/use-snapshot";
|
||||
@@ -41,11 +43,9 @@ import { AppContext, useAppContext } from "@/new/photos/types/context";
|
||||
import { initiateEmail, openURL } from "@/new/photos/utils/web";
|
||||
import {
|
||||
FlexWrapper,
|
||||
SpaceBetweenFlex,
|
||||
VerticallyCentered,
|
||||
} from "@ente/shared/components/Container";
|
||||
import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem";
|
||||
import DialogTitleWithCloseButton from "@ente/shared/components/TitleWithCloseButton";
|
||||
import { PHOTOS_PAGES as PAGES } from "@ente/shared/constants/pages";
|
||||
import { THEME_COLOR } from "@ente/shared/themes/constants";
|
||||
import ArchiveOutlined from "@mui/icons-material/ArchiveOutlined";
|
||||
@@ -136,10 +136,12 @@ interface HeaderSectionProps {
|
||||
|
||||
const HeaderSection: React.FC<HeaderSectionProps> = ({ closeSidebar }) => {
|
||||
return (
|
||||
<SpaceBetweenFlex mt={0.5} mb={1} pl={1.5}>
|
||||
<SpaceBetweenFlex
|
||||
sx={{ marginBlock: "4px 4px", paddingInlineStart: "12px" }}
|
||||
>
|
||||
<EnteLogo />
|
||||
<IconButton
|
||||
aria-label="close"
|
||||
aria-label={t("close")}
|
||||
onClick={closeSidebar}
|
||||
color="secondary"
|
||||
>
|
||||
@@ -344,12 +346,17 @@ function MemberSubscriptionManage({ open, userDetails, onClose }) {
|
||||
|
||||
return (
|
||||
<Dialog {...{ open, onClose, fullScreen }} maxWidth="xs" fullWidth>
|
||||
<DialogTitleWithCloseButton onClose={onClose}>
|
||||
<Typography variant="h3" fontWeight={"bold"}>
|
||||
{t("subscription")}
|
||||
</Typography>
|
||||
<Typography color={"text.muted"}>{t("family_plan")}</Typography>
|
||||
</DialogTitleWithCloseButton>
|
||||
<SpaceBetweenFlex sx={{ p: "20px 8px 12px 16px" }}>
|
||||
<Stack>
|
||||
<Typography variant="h3" fontWeight={"bold"}>
|
||||
{t("subscription")}
|
||||
</Typography>
|
||||
<Typography color={"text.muted"}>
|
||||
{t("family_plan")}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<DialogCloseIconButton {...{ onClose }} />
|
||||
</SpaceBetweenFlex>
|
||||
<DialogContent>
|
||||
<VerticallyCentered>
|
||||
<Box mb={4}>
|
||||
|
||||
@@ -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,9 +1,5 @@
|
||||
import {
|
||||
UPLOAD_RESULT,
|
||||
UPLOAD_STAGES,
|
||||
} from "@/new/photos/services/upload/types";
|
||||
import { dialogCloseHandler } from "@ente/shared/components/TitleWithCloseButton";
|
||||
import { Dialog, DialogContent } from "@mui/material";
|
||||
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";
|
||||
import { Trans } from "react-i18next";
|
||||
@@ -15,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,
|
||||
);
|
||||
|
||||
@@ -37,90 +33,73 @@ export function UploadProgressDialog() {
|
||||
}
|
||||
}, [finishedUploads]);
|
||||
|
||||
const handleClose = dialogCloseHandler({ staticBackdrop: true, onClose });
|
||||
const handleClose: DialogProps["onClose"] = (_, reason) => {
|
||||
if (reason != "backdropClick") onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={handleClose} maxWidth="xs" fullWidth>
|
||||
<UploadProgressHeader />
|
||||
{(uploadStage === UPLOAD_STAGES.UPLOADING ||
|
||||
uploadStage === UPLOAD_STAGES.FINISH ||
|
||||
uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA) && (
|
||||
{(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) && (
|
||||
<>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.UPLOADED}
|
||||
sectionTitle={t("SUCCESSFUL_UPLOADS")}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={
|
||||
UPLOAD_RESULT.UPLOADED_WITH_STATIC_THUMBNAIL
|
||||
}
|
||||
sectionTitle={t(
|
||||
"THUMBNAIL_GENERATION_FAILED_UPLOADS",
|
||||
)}
|
||||
sectionInfo={t(
|
||||
"THUMBNAIL_GENERATION_FAILED_INFO",
|
||||
)}
|
||||
/>
|
||||
{uploadStage === UPLOAD_STAGES.FINISH &&
|
||||
hasUnUploadedFiles && (
|
||||
<NotUploadSectionHeader>
|
||||
{t("FILE_NOT_UPLOADED_LIST")}
|
||||
</NotUploadSectionHeader>
|
||||
)}
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.BLOCKED}
|
||||
sectionTitle={t("BLOCKED_UPLOADS")}
|
||||
sectionInfo={
|
||||
<Trans i18nKey={"ETAGS_BLOCKED"} />
|
||||
}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.FAILED}
|
||||
sectionTitle={t("FAILED_UPLOADS")}
|
||||
sectionInfo={
|
||||
uploadStage === UPLOAD_STAGES.FINISH
|
||||
? undefined
|
||||
: t("failed_uploads_hint")
|
||||
}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.ALREADY_UPLOADED}
|
||||
sectionTitle={t("SKIPPED_FILES")}
|
||||
sectionInfo={t("SKIPPED_INFO")}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={
|
||||
UPLOAD_RESULT.LARGER_THAN_AVAILABLE_STORAGE
|
||||
}
|
||||
sectionTitle={t(
|
||||
"LARGER_THAN_AVAILABLE_STORAGE_UPLOADS",
|
||||
)}
|
||||
sectionInfo={t(
|
||||
"LARGER_THAN_AVAILABLE_STORAGE_INFO",
|
||||
)}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.UNSUPPORTED}
|
||||
sectionTitle={t("UNSUPPORTED_FILES")}
|
||||
sectionInfo={t("UNSUPPORTED_INFO")}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.TOO_LARGE}
|
||||
sectionTitle={t("TOO_LARGE_UPLOADS")}
|
||||
sectionInfo={t("TOO_LARGE_INFO")}
|
||||
/>
|
||||
</>
|
||||
{uploadPhase === "uploading" && <InProgressSection />}
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.UPLOADED}
|
||||
sectionTitle={t("SUCCESSFUL_UPLOADS")}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={
|
||||
UPLOAD_RESULT.UPLOADED_WITH_STATIC_THUMBNAIL
|
||||
}
|
||||
sectionTitle={t("THUMBNAIL_GENERATION_FAILED_UPLOADS")}
|
||||
sectionInfo={t("THUMBNAIL_GENERATION_FAILED_INFO")}
|
||||
/>
|
||||
{uploadPhase == "done" && hasUnUploadedFiles && (
|
||||
<NotUploadSectionHeader>
|
||||
{t("FILE_NOT_UPLOADED_LIST")}
|
||||
</NotUploadSectionHeader>
|
||||
)}
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.BLOCKED}
|
||||
sectionTitle={t("BLOCKED_UPLOADS")}
|
||||
sectionInfo={<Trans i18nKey={"ETAGS_BLOCKED"} />}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.FAILED}
|
||||
sectionTitle={t("FAILED_UPLOADS")}
|
||||
sectionInfo={
|
||||
uploadPhase == "done"
|
||||
? undefined
|
||||
: t("failed_uploads_hint")
|
||||
}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.ALREADY_UPLOADED}
|
||||
sectionTitle={t("SKIPPED_FILES")}
|
||||
sectionInfo={t("SKIPPED_INFO")}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={
|
||||
UPLOAD_RESULT.LARGER_THAN_AVAILABLE_STORAGE
|
||||
}
|
||||
sectionTitle={t(
|
||||
"LARGER_THAN_AVAILABLE_STORAGE_UPLOADS",
|
||||
)}
|
||||
sectionInfo={t("LARGER_THAN_AVAILABLE_STORAGE_INFO")}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.UNSUPPORTED}
|
||||
sectionTitle={t("UNSUPPORTED_FILES")}
|
||||
sectionInfo={t("UNSUPPORTED_INFO")}
|
||||
/>
|
||||
<ResultSection
|
||||
uploadResult={UPLOAD_RESULT.TOO_LARGE}
|
||||
sectionTitle={t("TOO_LARGE_UPLOADS")}
|
||||
sectionInfo={t("TOO_LARGE_INFO")}
|
||||
/>
|
||||
</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>
|
||||
@@ -46,11 +45,7 @@ export const InProgressSection = () => {
|
||||
<UploadProgressSection>
|
||||
<UploadProgressSectionTitle expandIcon={<ExpandMoreIcon />}>
|
||||
<CaptionedText
|
||||
mainText={
|
||||
uploadStage === UPLOAD_STAGES.EXTRACTING_METADATA
|
||||
? t("INPROGRESS_METADATA_EXTRACTION")
|
||||
: t("INPROGRESS_UPLOADS")
|
||||
}
|
||||
mainText={t("INPROGRESS_UPLOADS")}
|
||||
subText={String(inProgressUploads?.length ?? 0)}
|
||||
/>
|
||||
</UploadProgressSectionTitle>
|
||||
|
||||
@@ -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,13 @@
|
||||
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 == "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,29 @@ 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 "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,
|
||||
|
||||
@@ -3,13 +3,10 @@ import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton";
|
||||
import { useIsTouchscreen } from "@/base/hooks";
|
||||
import { DialogCloseIconButton } from "@/new/photos/components/mui/Dialog";
|
||||
import { EnteMenuItem } from "@ente/shared/components/Menu/EnteMenuItem";
|
||||
import DialogTitleWithCloseButton, {
|
||||
dialogCloseHandler,
|
||||
} from "@ente/shared/components/TitleWithCloseButton";
|
||||
import ChevronRight from "@mui/icons-material/ChevronRight";
|
||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||
import GoogleIcon from "@mui/icons-material/Google";
|
||||
import { default as FileUploadIcon } from "@mui/icons-material/ImageOutlined";
|
||||
import { default as FolderUploadIcon } from "@mui/icons-material/PermMediaOutlined";
|
||||
import ImageOutlinedIcon from "@mui/icons-material/ImageOutlined";
|
||||
import PermMediaOutlinedIcon from "@mui/icons-material/PermMediaOutlined";
|
||||
import {
|
||||
Box,
|
||||
Dialog,
|
||||
@@ -97,7 +94,7 @@ export const UploadTypeSelector: React.FC<UploadTypeSelectorProps> = ({
|
||||
[theme.breakpoints.down(360)]: { p: 0 },
|
||||
}),
|
||||
}}
|
||||
onClose={dialogCloseHandler({ onClose: onClose })}
|
||||
onClose={onClose}
|
||||
>
|
||||
<Options
|
||||
intent={intent}
|
||||
@@ -128,15 +125,13 @@ export const Options: React.FC<OptionsProps> = ({
|
||||
// Keep dialog content specific state here, in a separate component, so that
|
||||
// this state is not tied to the lifetime of the dialog.
|
||||
//
|
||||
// If we don't do this, then the dialog retains whatever it was doing when
|
||||
// If we don't do this, then a MUI dialog retains whatever it was doing when
|
||||
// it was last closed. Sometimes that is desirable, but sometimes not, and
|
||||
// in the latter cases moving the instance specific state to a child works.
|
||||
|
||||
const [showTakeoutOptions, setShowTakeoutOptions] = useState(false);
|
||||
|
||||
const handleTakeoutClose = () => {
|
||||
setShowTakeoutOptions(false);
|
||||
};
|
||||
const handleTakeoutClose = () => setShowTakeoutOptions(false);
|
||||
|
||||
const handleSelect = (option: OptionType) => {
|
||||
switch (option) {
|
||||
@@ -168,44 +163,45 @@ const DefaultOptions: React.FC<OptionsProps> = ({
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<DialogTitleWithCloseButton onClose={onClose}>
|
||||
{intent == "collect"
|
||||
? t("select_photos")
|
||||
: intent == "import"
|
||||
? t("import")
|
||||
: t("upload")}
|
||||
</DialogTitleWithCloseButton>
|
||||
<SpaceBetweenFlex>
|
||||
<DialogTitle variant="h5">
|
||||
{intent == "collect"
|
||||
? t("select_photos")
|
||||
: intent == "import"
|
||||
? t("import")
|
||||
: t("upload")}
|
||||
</DialogTitle>
|
||||
<DialogCloseIconButton {...{ onClose }} />
|
||||
</SpaceBetweenFlex>
|
||||
|
||||
<Box p={1.5} pt={0.5}>
|
||||
<Box sx={{ p: "12px", pt: "16px" }}>
|
||||
<Stack spacing={0.5}>
|
||||
{intent != "import" && (
|
||||
<EnteMenuItem
|
||||
onClick={() => onSelect("files")}
|
||||
startIcon={<FileUploadIcon />}
|
||||
endIcon={<ChevronRight />}
|
||||
startIcon={<ImageOutlinedIcon />}
|
||||
endIcon={<ChevronRightIcon />}
|
||||
label={t("file")}
|
||||
/>
|
||||
)}
|
||||
<EnteMenuItem
|
||||
onClick={() => onSelect("folders")}
|
||||
startIcon={<FolderUploadIcon />}
|
||||
endIcon={<ChevronRight />}
|
||||
startIcon={<PermMediaOutlinedIcon />}
|
||||
endIcon={<ChevronRightIcon />}
|
||||
label={t("folder")}
|
||||
/>
|
||||
{intent !== "collect" && (
|
||||
<EnteMenuItem
|
||||
onClick={() => onSelect("zips")}
|
||||
startIcon={<GoogleIcon />}
|
||||
endIcon={<ChevronRight />}
|
||||
endIcon={<ChevronRightIcon />}
|
||||
label={t("google_takeout")}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
<Typography
|
||||
p={1.5}
|
||||
pt={4}
|
||||
color="text.muted"
|
||||
sx={{ textAlign: "center" }}
|
||||
sx={{ p: "12px", pt: "24px", textAlign: "center" }}
|
||||
>
|
||||
{t("drag_and_drop_hint")}
|
||||
</Typography>
|
||||
@@ -220,13 +216,13 @@ const TakeoutOptions: React.FC<Omit<OptionsProps, "intent">> = ({
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<SpaceBetweenFlex sx={{ padding: "8px 8px 0px 0" }}>
|
||||
<SpaceBetweenFlex>
|
||||
<DialogTitle variant="h5">{t("google_takeout")}</DialogTitle>
|
||||
<DialogCloseIconButton {...{ onClose }} />
|
||||
</SpaceBetweenFlex>
|
||||
|
||||
<Stack sx={{ padding: "12px", gap: "20px" }}>
|
||||
<Stack gap={1}>
|
||||
<Stack sx={{ padding: "18px 12px 20px 12px", gap: "16px" }}>
|
||||
<Stack sx={{ gap: "8px" }}>
|
||||
<FocusVisibleButton
|
||||
color="accent"
|
||||
fullWidth
|
||||
@@ -252,7 +248,7 @@ const TakeoutOptions: React.FC<Omit<OptionsProps, "intent">> = ({
|
||||
</Link>
|
||||
</Stack>
|
||||
|
||||
<Typography variant="small" color="text.muted" pb={1}>
|
||||
<Typography variant="small" color="text.muted">
|
||||
{t("takeout_hint")}
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { ensureElectron } from "@/base/electron";
|
||||
import { basename, dirname } from "@/base/file";
|
||||
import type { CollectionMapping, FolderWatch } from "@/base/types/ipc";
|
||||
import { CollectionMappingChoiceDialog } from "@/new/photos/components/CollectionMappingChoiceDialog";
|
||||
import { DialogCloseIconButton } from "@/new/photos/components/mui/Dialog";
|
||||
import { AppContext, useAppContext } from "@/new/photos/types/context";
|
||||
import { ensure } from "@/utils/ensure";
|
||||
import {
|
||||
@@ -17,7 +18,6 @@ import {
|
||||
} from "@ente/shared/components/Container";
|
||||
import OverflowMenu from "@ente/shared/components/OverflowMenu/menu";
|
||||
import { OverflowMenuOption } from "@ente/shared/components/OverflowMenu/option";
|
||||
import DialogTitleWithCloseButton from "@ente/shared/components/TitleWithCloseButton";
|
||||
import CheckIcon from "@mui/icons-material/Check";
|
||||
import DoNotDisturbOutlinedIcon from "@mui/icons-material/DoNotDisturbOutlined";
|
||||
import FolderCopyOutlinedIcon from "@mui/icons-material/FolderCopyOutlined";
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
CircularProgress,
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Stack,
|
||||
Tooltip,
|
||||
Typography,
|
||||
@@ -119,11 +120,12 @@ export const WatchFolder: React.FC<ModalVisibilityProps> = ({
|
||||
fullWidth
|
||||
PaperProps={{ sx: { height: "448px", maxWidth: "414px" } }}
|
||||
>
|
||||
<Title_>
|
||||
<DialogTitleWithCloseButton onClose={onClose}>
|
||||
<SpaceBetweenFlex sx={{ p: "16px 8px 8px 8px" }}>
|
||||
<DialogTitle variant="h3" fontWeight={"bold"}>
|
||||
{t("WATCHED_FOLDERS")}
|
||||
</DialogTitleWithCloseButton>
|
||||
</Title_>
|
||||
</DialogTitle>
|
||||
<DialogCloseIconButton {...{ onClose }} />
|
||||
</SpaceBetweenFlex>
|
||||
<DialogContent sx={{ flex: 1 }}>
|
||||
<Stack spacing={1} p={1.5} height={"100%"}>
|
||||
<WatchList {...{ watches, removeWatch }} />
|
||||
@@ -147,10 +149,6 @@ export const WatchFolder: React.FC<ModalVisibilityProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const Title_ = styled("div")`
|
||||
padding: 16px 12px 16px 16px;
|
||||
`;
|
||||
|
||||
interface WatchList {
|
||||
watches: FolderWatch[] | undefined;
|
||||
removeWatch: (watch: FolderWatch) => void;
|
||||
|
||||
@@ -90,7 +90,7 @@ import CollectionNamer, {
|
||||
CollectionNamerAttributes,
|
||||
} from "components/Collections/CollectionNamer";
|
||||
import { GalleryBarAndListHeader } from "components/Collections/GalleryBarAndListHeader";
|
||||
import ExportModal from "components/ExportModal";
|
||||
import { Export } from "components/Export";
|
||||
import {
|
||||
FilesDownloadProgress,
|
||||
FilesDownloadProgressAttributes,
|
||||
@@ -249,8 +249,6 @@ export default function Gallery() {
|
||||
const closeSidebar = () => setSidebarView(false);
|
||||
const openSidebar = () => setSidebarView(true);
|
||||
|
||||
const [exportModalView, setExportModalView] = useState(false);
|
||||
|
||||
const [authenticateUserModalView, setAuthenticateUserModalView] =
|
||||
useState(false);
|
||||
|
||||
@@ -297,6 +295,8 @@ export default function Gallery() {
|
||||
useModalVisibility();
|
||||
const { show: showFixCreationTime, props: fixCreationTimeVisibilityProps } =
|
||||
useModalVisibility();
|
||||
const { show: showExport, props: exportVisibilityProps } =
|
||||
useModalVisibility();
|
||||
|
||||
// TODO: Temp
|
||||
const user = state.user;
|
||||
@@ -496,7 +496,7 @@ export default function Gallery() {
|
||||
collectionNamerView ||
|
||||
planSelectorVisibilityProps.open ||
|
||||
fixCreationTimeVisibilityProps.open ||
|
||||
exportModalView ||
|
||||
exportVisibilityProps.open ||
|
||||
authenticateUserModalView ||
|
||||
isPhotoSwipeOpen ||
|
||||
!filteredFiles?.length ||
|
||||
@@ -810,14 +810,6 @@ export default function Gallery() {
|
||||
setUploadTypeSelectorIntent(intent ?? "upload");
|
||||
};
|
||||
|
||||
const openExportModal = () => {
|
||||
setExportModalView(true);
|
||||
};
|
||||
|
||||
const closeExportModal = () => {
|
||||
setExportModalView(false);
|
||||
};
|
||||
|
||||
const handleSetActiveCollectionID = (
|
||||
collectionSummaryID: number | undefined,
|
||||
) =>
|
||||
@@ -876,7 +868,7 @@ export default function Gallery() {
|
||||
syncWithRemote,
|
||||
setBlockingLoad,
|
||||
photoListHeader,
|
||||
openExportModal,
|
||||
openExportModal: showExport,
|
||||
authenticateUser,
|
||||
userIDToEmailMap,
|
||||
user,
|
||||
@@ -1115,9 +1107,8 @@ export default function Gallery() {
|
||||
isInHiddenSection={barMode == "hidden-albums"}
|
||||
/>
|
||||
)}
|
||||
<ExportModal
|
||||
show={exportModalView}
|
||||
onHide={closeExportModal}
|
||||
<Export
|
||||
{...exportVisibilityProps}
|
||||
collectionNameMap={state.allCollectionNameByID}
|
||||
/>
|
||||
<AuthenticateUserModal
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { type MiniDialogAttributes } from "@/base/components/MiniDialog";
|
||||
import { SpaceBetweenFlex } from "@/base/components/mui/Container";
|
||||
import { FocusVisibleButton } from "@/base/components/mui/FocusVisibleButton";
|
||||
import { errorDialogAttributes } from "@/base/components/utils/dialog";
|
||||
import type { ModalVisibilityProps } from "@/base/components/utils/modal";
|
||||
import { useIsSmallWidth } from "@/base/hooks";
|
||||
import log from "@/base/log";
|
||||
import { downloadString } from "@/base/utils/web";
|
||||
import { DialogCloseIconButton } from "@/new/photos/components/mui/Dialog";
|
||||
import { ensure } from "@/utils/ensure";
|
||||
import CodeBlock from "@ente/shared/components/CodeBlock";
|
||||
import DialogTitleWithCloseButton from "@ente/shared/components/TitleWithCloseButton";
|
||||
import { getRecoveryKey } from "@ente/shared/crypto/helpers";
|
||||
import {
|
||||
Box,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Typography,
|
||||
styled,
|
||||
} from "@mui/material";
|
||||
@@ -74,9 +76,13 @@ export const RecoveryKey: React.FC<RecoveryKeyProps> = ({
|
||||
maxWidth="xs"
|
||||
fullWidth
|
||||
>
|
||||
<DialogTitleWithCloseButton onClose={onClose}>
|
||||
{t("recovery_key")}
|
||||
</DialogTitleWithCloseButton>
|
||||
<SpaceBetweenFlex sx={{ p: "8px 4px 8px 0" }}>
|
||||
<DialogTitle variant="h3" fontWeight={"bold"}>
|
||||
{t("recovery_key")}
|
||||
</DialogTitle>
|
||||
<DialogCloseIconButton {...{ onClose }} />
|
||||
</SpaceBetweenFlex>
|
||||
|
||||
<DialogContent>
|
||||
<Typography mb={3}>{t("recovery_key_description")}</Typography>
|
||||
<DashedBorderWrapper>
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
"UPLOAD_STAGE_MESSAGE": {
|
||||
"0": "Preparing to upload",
|
||||
"1": "Reading google metadata files",
|
||||
"2": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files metadata extracted",
|
||||
"3": "{{uploadCounter.finished, number}} / {{uploadCounter.total, number}} files processed",
|
||||
"4": "Cancelling remaining uploads",
|
||||
"5": "Backup complete"
|
||||
@@ -307,7 +306,6 @@
|
||||
"SKIPPED_INFO": "Skipped these as there are files with matching name and content in the same album",
|
||||
"UNSUPPORTED_INFO": "Ente does not support these file formats yet",
|
||||
"BLOCKED_UPLOADS": "Blocked uploads",
|
||||
"INPROGRESS_METADATA_EXTRACTION": "In progress",
|
||||
"INPROGRESS_UPLOADS": "Uploads in progress",
|
||||
"TOO_LARGE_UPLOADS": "Large files",
|
||||
"LARGER_THAN_AVAILABLE_STORAGE_UPLOADS": "Insufficient storage",
|
||||
|
||||
@@ -58,14 +58,12 @@ 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"
|
||||
| "uploading"
|
||||
| "cancelling"
|
||||
| "done";
|
||||
|
||||
export enum UPLOAD_RESULT {
|
||||
FAILED,
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import { SpaceBetweenFlex } from "@ente/shared/components/Container";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import {
|
||||
DialogTitle,
|
||||
IconButton,
|
||||
Typography,
|
||||
type DialogProps,
|
||||
} from "@mui/material";
|
||||
import React from "react";
|
||||
|
||||
interface DialogTitleWithCloseButtonProps {
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
const DialogTitleWithCloseButton: React.FC<
|
||||
React.PropsWithChildren<DialogTitleWithCloseButtonProps>
|
||||
> = ({ children, onClose }) => {
|
||||
return (
|
||||
<DialogTitle>
|
||||
<SpaceBetweenFlex>
|
||||
<Typography variant="h3" fontWeight={"bold"}>
|
||||
{children}
|
||||
</Typography>
|
||||
{onClose && (
|
||||
<IconButton
|
||||
aria-label="close"
|
||||
onClick={onClose}
|
||||
sx={{ float: "right" }}
|
||||
color="secondary"
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
</SpaceBetweenFlex>
|
||||
</DialogTitle>
|
||||
);
|
||||
};
|
||||
export default DialogTitleWithCloseButton;
|
||||
|
||||
export const dialogCloseHandler =
|
||||
({
|
||||
staticBackdrop,
|
||||
nonClosable,
|
||||
onClose,
|
||||
}: {
|
||||
staticBackdrop?: boolean;
|
||||
nonClosable?: boolean;
|
||||
onClose: () => void;
|
||||
}): DialogProps["onClose"] =>
|
||||
(_, reason) => {
|
||||
if (nonClosable) {
|
||||
// no-op
|
||||
} else if (staticBackdrop && reason === "backdropClick") {
|
||||
// no-op
|
||||
} else {
|
||||
onClose();
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user