Inline 1
This commit is contained in:
@@ -1,14 +1,26 @@
|
||||
import { UPLOAD_RESULT } from "@/new/photos/services/upload/types";
|
||||
import { Dialog, DialogContent, type DialogProps } from "@mui/material";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
styled,
|
||||
type DialogProps,
|
||||
} from "@mui/material";
|
||||
import { CaptionedText } from "components/CaptionedText";
|
||||
import ItemList from "components/ItemList";
|
||||
import { t } from "i18next";
|
||||
import { useContext, useEffect, useState } from "react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { Trans } from "react-i18next";
|
||||
import UploadProgressContext from "./context";
|
||||
import { UploadProgressFooter } from "./footer";
|
||||
import { UploadProgressHeader } from "./header";
|
||||
import { InProgressSection } from "./inProgressSection";
|
||||
import { ResultSection } from "./resultSection";
|
||||
import { NotUploadSectionHeader } from "./styledComponents";
|
||||
import {
|
||||
SectionInfo,
|
||||
UploadProgressSection,
|
||||
UploadProgressSectionContent,
|
||||
UploadProgressSectionTitle,
|
||||
} from "./section";
|
||||
|
||||
export function UploadProgressDialog() {
|
||||
const { open, onClose, uploadPhase, finishedUploads } = useContext(
|
||||
@@ -103,3 +115,172 @@ export function UploadProgressDialog() {
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
const InProgressSection: React.FC = () => {
|
||||
const { inProgressUploads, hasLivePhotos, uploadFileNames, uploadPhase } =
|
||||
useContext(UploadProgressContext);
|
||||
const fileList = inProgressUploads ?? [];
|
||||
|
||||
const renderListItem = ({ localFileID, progress }) => {
|
||||
return (
|
||||
<InProgressItemContainer key={localFileID}>
|
||||
<span>{uploadFileNames.get(localFileID)}</span>
|
||||
{uploadPhase == "uploading" && (
|
||||
<>
|
||||
{" "}
|
||||
<span className="separator">{`-`}</span>
|
||||
<span>{`${progress}%`}</span>
|
||||
</>
|
||||
)}
|
||||
</InProgressItemContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const getItemTitle = ({ localFileID, progress }) => {
|
||||
return `${uploadFileNames.get(localFileID)} - ${progress}%`;
|
||||
};
|
||||
|
||||
const generateItemKey = ({ localFileID, progress }) => {
|
||||
return `${localFileID}-${progress}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<UploadProgressSection>
|
||||
<UploadProgressSectionTitle expandIcon={<ExpandMoreIcon />}>
|
||||
<CaptionedText
|
||||
mainText={t("INPROGRESS_UPLOADS")}
|
||||
subText={String(inProgressUploads?.length ?? 0)}
|
||||
/>
|
||||
</UploadProgressSectionTitle>
|
||||
<UploadProgressSectionContent>
|
||||
{hasLivePhotos && (
|
||||
<SectionInfo>{t("LIVE_PHOTOS_DETECTED")}</SectionInfo>
|
||||
)}
|
||||
<ItemList
|
||||
items={fileList}
|
||||
generateItemKey={generateItemKey}
|
||||
getItemTitle={getItemTitle}
|
||||
renderListItem={renderListItem}
|
||||
maxHeight={160}
|
||||
itemSize={35}
|
||||
/>
|
||||
</UploadProgressSectionContent>
|
||||
</UploadProgressSection>
|
||||
);
|
||||
};
|
||||
|
||||
const InProgressItemContainer = styled("div")`
|
||||
display: inline-block;
|
||||
& > span {
|
||||
display: inline-block;
|
||||
}
|
||||
& > span:first-of-type {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
max-width: 340px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
& > .separator {
|
||||
margin: 0 5px;
|
||||
}
|
||||
`;
|
||||
|
||||
const NotUploadSectionHeader = styled("div")(
|
||||
({ theme }) => `
|
||||
text-align: center;
|
||||
color: ${theme.colors.danger.A700};
|
||||
border-bottom: 1px solid ${theme.colors.danger.A700};
|
||||
margin:${theme.spacing(3, 2, 1)}
|
||||
`,
|
||||
);
|
||||
|
||||
const UploadProgressFooter: React.FC = () => {
|
||||
const { uploadPhase, finishedUploads, retryFailed, onClose } = useContext(
|
||||
UploadProgressContext,
|
||||
);
|
||||
|
||||
return (
|
||||
<DialogActions>
|
||||
{uploadPhase == "done" &&
|
||||
(finishedUploads?.get(UPLOAD_RESULT.FAILED)?.length > 0 ||
|
||||
finishedUploads?.get(UPLOAD_RESULT.BLOCKED)?.length > 0 ? (
|
||||
<Button variant="contained" fullWidth onClick={retryFailed}>
|
||||
{t("RETRY_FAILED")}
|
||||
</Button>
|
||||
) : (
|
||||
<Button variant="contained" fullWidth onClick={onClose}>
|
||||
{t("close")}
|
||||
</Button>
|
||||
))}
|
||||
</DialogActions>
|
||||
);
|
||||
};
|
||||
|
||||
interface ResultSectionProps {
|
||||
uploadResult: UPLOAD_RESULT;
|
||||
sectionTitle: any;
|
||||
sectionInfo?: any;
|
||||
}
|
||||
|
||||
const ResultSection = (props: ResultSectionProps) => {
|
||||
const { finishedUploads, uploadFileNames } = useContext(
|
||||
UploadProgressContext,
|
||||
);
|
||||
const fileList = finishedUploads.get(props.uploadResult);
|
||||
|
||||
if (!fileList?.length) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const renderListItem = (fileID) => {
|
||||
return (
|
||||
<ResultItemContainer key={fileID}>
|
||||
{uploadFileNames.get(fileID)}
|
||||
</ResultItemContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const getItemTitle = (fileID) => {
|
||||
return uploadFileNames.get(fileID);
|
||||
};
|
||||
|
||||
const generateItemKey = (fileID) => {
|
||||
return fileID;
|
||||
};
|
||||
|
||||
return (
|
||||
<UploadProgressSection>
|
||||
<UploadProgressSectionTitle expandIcon={<ExpandMoreIcon />}>
|
||||
<CaptionedText
|
||||
mainText={props.sectionTitle}
|
||||
subText={String(fileList?.length ?? 0)}
|
||||
/>
|
||||
</UploadProgressSectionTitle>
|
||||
<UploadProgressSectionContent>
|
||||
{props.sectionInfo && (
|
||||
<SectionInfo>{props.sectionInfo}</SectionInfo>
|
||||
)}
|
||||
<ItemList
|
||||
items={fileList}
|
||||
generateItemKey={generateItemKey}
|
||||
getItemTitle={getItemTitle}
|
||||
renderListItem={renderListItem}
|
||||
maxHeight={160}
|
||||
itemSize={35}
|
||||
/>
|
||||
</UploadProgressSectionContent>
|
||||
</UploadProgressSection>
|
||||
);
|
||||
};
|
||||
|
||||
const ResultItemContainer = styled("div")`
|
||||
position: relative;
|
||||
top: 5px;
|
||||
display: inline-block;
|
||||
max-width: 394px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
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 { uploadPhase, finishedUploads, retryFailed, onClose } = useContext(
|
||||
UploadProgressContext,
|
||||
);
|
||||
|
||||
return (
|
||||
<DialogActions>
|
||||
{uploadPhase == "done" &&
|
||||
(finishedUploads?.get(UPLOAD_RESULT.FAILED)?.length > 0 ||
|
||||
finishedUploads?.get(UPLOAD_RESULT.BLOCKED)?.length > 0 ? (
|
||||
<Button variant="contained" fullWidth onClick={retryFailed}>
|
||||
{t("RETRY_FAILED")}
|
||||
</Button>
|
||||
) : (
|
||||
<Button variant="contained" fullWidth onClick={onClose}>
|
||||
{t("close")}
|
||||
</Button>
|
||||
))}
|
||||
</DialogActions>
|
||||
);
|
||||
}
|
||||
@@ -1,5 +1,21 @@
|
||||
import { UploadProgressBar } from "./progressBar";
|
||||
import { UploadProgressTitle } from "./title";
|
||||
import { FilledIconButton } from "@/new/photos/components/mui";
|
||||
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";
|
||||
import UnfoldMoreIcon from "@mui/icons-material/UnfoldMore";
|
||||
import {
|
||||
Box,
|
||||
DialogTitle,
|
||||
Divider,
|
||||
LinearProgress,
|
||||
Stack,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { t } from "i18next";
|
||||
import React, { useContext } from "react";
|
||||
import type { UploadCounter } from "services/upload/uploadManager";
|
||||
import UploadProgressContext from "./context";
|
||||
|
||||
export function UploadProgressHeader() {
|
||||
return (
|
||||
@@ -9,3 +25,94 @@ export function UploadProgressHeader() {
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const UploadProgressTitleText = ({ expanded }) => {
|
||||
return (
|
||||
<Typography variant={expanded ? "h2" : "h3"}>
|
||||
{t("FILE_UPLOAD")}
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
function UploadProgressSubtitleText() {
|
||||
const { uploadPhase, uploadCounter } = useContext(UploadProgressContext);
|
||||
|
||||
return (
|
||||
<Typography
|
||||
variant="body"
|
||||
fontWeight={"normal"}
|
||||
color="text.muted"
|
||||
marginTop={"4px"}
|
||||
>
|
||||
{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");
|
||||
}
|
||||
};
|
||||
|
||||
const UploadProgressTitle: React.FC = () => {
|
||||
const { setExpanded, onClose, expanded } = useContext(
|
||||
UploadProgressContext,
|
||||
);
|
||||
const toggleExpanded = () => setExpanded((expanded) => !expanded);
|
||||
|
||||
return (
|
||||
<DialogTitle>
|
||||
<SpaceBetweenFlex>
|
||||
<Box>
|
||||
<UploadProgressTitleText expanded={expanded} />
|
||||
<UploadProgressSubtitleText />
|
||||
</Box>
|
||||
<Box>
|
||||
<Stack direction={"row"} spacing={1}>
|
||||
<FilledIconButton onClick={toggleExpanded}>
|
||||
{expanded ? <UnfoldLessIcon /> : <UnfoldMoreIcon />}
|
||||
</FilledIconButton>
|
||||
<FilledIconButton onClick={onClose}>
|
||||
<Close />
|
||||
</FilledIconButton>
|
||||
</Stack>
|
||||
</Box>
|
||||
</SpaceBetweenFlex>
|
||||
</DialogTitle>
|
||||
);
|
||||
};
|
||||
|
||||
const UploadProgressBar: React.FC = () => {
|
||||
const { uploadPhase, percentComplete } = useContext(UploadProgressContext);
|
||||
return (
|
||||
<Box>
|
||||
{(uploadPhase == "readingMetadata" ||
|
||||
uploadPhase == "uploading") && (
|
||||
<>
|
||||
<LinearProgress
|
||||
sx={{
|
||||
height: "2px",
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
variant="determinate"
|
||||
value={percentComplete}
|
||||
/>
|
||||
<Divider />
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import ItemList from "components/ItemList";
|
||||
import { t } from "i18next";
|
||||
import { useContext } from "react";
|
||||
import UploadProgressContext from "./context";
|
||||
import {
|
||||
SectionInfo,
|
||||
UploadProgressSection,
|
||||
UploadProgressSectionContent,
|
||||
UploadProgressSectionTitle,
|
||||
} from "./section";
|
||||
import { InProgressItemContainer } from "./styledComponents";
|
||||
|
||||
import { CaptionedText } from "components/CaptionedText";
|
||||
|
||||
export const InProgressSection = () => {
|
||||
const { inProgressUploads, hasLivePhotos, uploadFileNames, uploadPhase } =
|
||||
useContext(UploadProgressContext);
|
||||
const fileList = inProgressUploads ?? [];
|
||||
|
||||
const renderListItem = ({ localFileID, progress }) => {
|
||||
return (
|
||||
<InProgressItemContainer key={localFileID}>
|
||||
<span>{uploadFileNames.get(localFileID)}</span>
|
||||
{uploadPhase == "uploading" && (
|
||||
<>
|
||||
{" "}
|
||||
<span className="separator">{`-`}</span>
|
||||
<span>{`${progress}%`}</span>
|
||||
</>
|
||||
)}
|
||||
</InProgressItemContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const getItemTitle = ({ localFileID, progress }) => {
|
||||
return `${uploadFileNames.get(localFileID)} - ${progress}%`;
|
||||
};
|
||||
|
||||
const generateItemKey = ({ localFileID, progress }) => {
|
||||
return `${localFileID}-${progress}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<UploadProgressSection>
|
||||
<UploadProgressSectionTitle expandIcon={<ExpandMoreIcon />}>
|
||||
<CaptionedText
|
||||
mainText={t("INPROGRESS_UPLOADS")}
|
||||
subText={String(inProgressUploads?.length ?? 0)}
|
||||
/>
|
||||
</UploadProgressSectionTitle>
|
||||
<UploadProgressSectionContent>
|
||||
{hasLivePhotos && (
|
||||
<SectionInfo>{t("LIVE_PHOTOS_DETECTED")}</SectionInfo>
|
||||
)}
|
||||
<ItemList
|
||||
items={fileList}
|
||||
generateItemKey={generateItemKey}
|
||||
getItemTitle={getItemTitle}
|
||||
renderListItem={renderListItem}
|
||||
maxHeight={160}
|
||||
itemSize={35}
|
||||
/>
|
||||
</UploadProgressSectionContent>
|
||||
</UploadProgressSection>
|
||||
);
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
import { Box, Divider, LinearProgress } from "@mui/material";
|
||||
import { useContext } from "react";
|
||||
import UploadProgressContext from "./context";
|
||||
|
||||
export function UploadProgressBar() {
|
||||
const { uploadPhase, percentComplete } = useContext(UploadProgressContext);
|
||||
return (
|
||||
<Box>
|
||||
{(uploadPhase == "readingMetadata" ||
|
||||
uploadPhase == "uploading") && (
|
||||
<>
|
||||
<LinearProgress
|
||||
sx={{
|
||||
height: "2px",
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
variant="determinate"
|
||||
value={percentComplete}
|
||||
/>
|
||||
<Divider />
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
import { UPLOAD_RESULT } from "@/new/photos/services/upload/types";
|
||||
import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
|
||||
import { CaptionedText } from "components/CaptionedText";
|
||||
import ItemList from "components/ItemList";
|
||||
import { useContext } from "react";
|
||||
import UploadProgressContext from "./context";
|
||||
import {
|
||||
SectionInfo,
|
||||
UploadProgressSection,
|
||||
UploadProgressSectionContent,
|
||||
UploadProgressSectionTitle,
|
||||
} from "./section";
|
||||
import { ResultItemContainer } from "./styledComponents";
|
||||
|
||||
export interface ResultSectionProps {
|
||||
uploadResult: UPLOAD_RESULT;
|
||||
sectionTitle: any;
|
||||
sectionInfo?: any;
|
||||
}
|
||||
export const ResultSection = (props: ResultSectionProps) => {
|
||||
const { finishedUploads, uploadFileNames } = useContext(
|
||||
UploadProgressContext,
|
||||
);
|
||||
const fileList = finishedUploads.get(props.uploadResult);
|
||||
|
||||
if (!fileList?.length) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const renderListItem = (fileID) => {
|
||||
return (
|
||||
<ResultItemContainer key={fileID}>
|
||||
{uploadFileNames.get(fileID)}
|
||||
</ResultItemContainer>
|
||||
);
|
||||
};
|
||||
|
||||
const getItemTitle = (fileID) => {
|
||||
return uploadFileNames.get(fileID);
|
||||
};
|
||||
|
||||
const generateItemKey = (fileID) => {
|
||||
return fileID;
|
||||
};
|
||||
|
||||
return (
|
||||
<UploadProgressSection>
|
||||
<UploadProgressSectionTitle expandIcon={<ExpandMoreIcon />}>
|
||||
<CaptionedText
|
||||
mainText={props.sectionTitle}
|
||||
subText={String(fileList?.length ?? 0)}
|
||||
/>
|
||||
</UploadProgressSectionTitle>
|
||||
<UploadProgressSectionContent>
|
||||
{props.sectionInfo && (
|
||||
<SectionInfo>{props.sectionInfo}</SectionInfo>
|
||||
)}
|
||||
<ItemList
|
||||
items={fileList}
|
||||
generateItemKey={generateItemKey}
|
||||
getItemTitle={getItemTitle}
|
||||
renderListItem={renderListItem}
|
||||
maxHeight={160}
|
||||
itemSize={35}
|
||||
/>
|
||||
</UploadProgressSectionContent>
|
||||
</UploadProgressSection>
|
||||
);
|
||||
};
|
||||
@@ -1,37 +0,0 @@
|
||||
import { styled } from "@mui/material";
|
||||
export const NotUploadSectionHeader = styled("div")(
|
||||
({ theme }) => `
|
||||
text-align: center;
|
||||
color: ${theme.colors.danger.A700};
|
||||
border-bottom: 1px solid ${theme.colors.danger.A700};
|
||||
margin:${theme.spacing(3, 2, 1)}
|
||||
`,
|
||||
);
|
||||
|
||||
export const InProgressItemContainer = styled("div")`
|
||||
display: inline-block;
|
||||
& > span {
|
||||
display: inline-block;
|
||||
}
|
||||
& > span:first-of-type {
|
||||
position: relative;
|
||||
top: 5px;
|
||||
max-width: 340px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
& > .separator {
|
||||
margin: 0 5px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const ResultItemContainer = styled("div")`
|
||||
position: relative;
|
||||
top: 5px;
|
||||
display: inline-block;
|
||||
max-width: 394px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
`;
|
||||
@@ -1,80 +0,0 @@
|
||||
import { FilledIconButton } from "@/new/photos/components/mui";
|
||||
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";
|
||||
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 }) => {
|
||||
return (
|
||||
<Typography variant={expanded ? "h2" : "h3"}>
|
||||
{t("FILE_UPLOAD")}
|
||||
</Typography>
|
||||
);
|
||||
};
|
||||
|
||||
function UploadProgressSubtitleText() {
|
||||
const { uploadPhase, uploadCounter } = useContext(UploadProgressContext);
|
||||
|
||||
return (
|
||||
<Typography
|
||||
variant="body"
|
||||
fontWeight={"normal"}
|
||||
color="text.muted"
|
||||
marginTop={"4px"}
|
||||
>
|
||||
{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,
|
||||
);
|
||||
const toggleExpanded = () => setExpanded((expanded) => !expanded);
|
||||
|
||||
return (
|
||||
<DialogTitle>
|
||||
<SpaceBetweenFlex>
|
||||
<Box>
|
||||
<UploadProgressTitleText expanded={expanded} />
|
||||
<UploadProgressSubtitleText />
|
||||
</Box>
|
||||
<Box>
|
||||
<Stack direction={"row"} spacing={1}>
|
||||
<FilledIconButton onClick={toggleExpanded}>
|
||||
{expanded ? <UnfoldLessIcon /> : <UnfoldMoreIcon />}
|
||||
</FilledIconButton>
|
||||
<FilledIconButton onClick={onClose}>
|
||||
<Close />
|
||||
</FilledIconButton>
|
||||
</Stack>
|
||||
</Box>
|
||||
</SpaceBetweenFlex>
|
||||
</DialogTitle>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user