diff --git a/web/apps/photos/src/components/Sidebar/index.tsx b/web/apps/photos/src/components/Sidebar/index.tsx index 4dcbfd5192..bd942acdc5 100644 --- a/web/apps/photos/src/components/Sidebar/index.tsx +++ b/web/apps/photos/src/components/Sidebar/index.tsx @@ -8,7 +8,7 @@ import log from "@/base/log"; import { savedLogs } from "@/base/log-web"; import { customAPIHost } from "@/base/origins"; import { RecoveryKey } from "@/new/photos/components/RecoveryKey"; -import { downloadAppDialogAttributes } from "@/new/photos/components/utils/dialog"; +import { downloadAppDialogAttributes } from "@/new/photos/components/utils/download"; import type { CollectionSummaries } from "@/new/photos/services/collection/ui"; import { AppContext, useAppContext } from "@/new/photos/types/context"; import { downloadString, initiateEmail, openURL } from "@/new/photos/utils/web"; diff --git a/web/apps/photos/src/components/Upload/Uploader.tsx b/web/apps/photos/src/components/Upload/Uploader.tsx index 5b09f6811c..5463aa466b 100644 --- a/web/apps/photos/src/components/Upload/Uploader.tsx +++ b/web/apps/photos/src/components/Upload/Uploader.tsx @@ -4,7 +4,7 @@ import type { CollectionMapping, Electron, ZipItem } from "@/base/types/ipc"; import type { Collection } from "@/media/collection"; import { CollectionMappingChoiceDialog } from "@/new/photos/components/CollectionMappingChoiceDialog"; import type { CollectionSelectorAttributes } from "@/new/photos/components/CollectionSelector"; -import { downloadAppDialogAttributes } from "@/new/photos/components/utils/dialog"; +import { downloadAppDialogAttributes } from "@/new/photos/components/utils/download"; import { exportMetadataDirectoryName } from "@/new/photos/services/export"; import type { FileAndPath, diff --git a/web/apps/photos/src/pages/_app.tsx b/web/apps/photos/src/pages/_app.tsx index 0c7b0f61c0..703a43fa63 100644 --- a/web/apps/photos/src/pages/_app.tsx +++ b/web/apps/photos/src/pages/_app.tsx @@ -14,6 +14,10 @@ import { logUnhandledErrorsAndRejections, } from "@/base/log-web"; import { AppUpdate } from "@/base/types/ipc"; +import { + updateAvailableForDownloadDialogAttributes, + updateReadyToInstallDialogAttributes, +} from "@/new/photos/components/utils/download"; import { photosDialogZIndex } from "@/new/photos/components/z-index"; import DownloadManager from "@/new/photos/services/download"; import { runMigrations } from "@/new/photos/services/migrations"; @@ -57,10 +61,6 @@ import { } from "services/userService"; import "styles/global.css"; import { NotificationAttributes } from "types/Notification"; -import { - getUpdateAvailableForDownloadMessage, - getUpdateReadyToInstallMessage, -} from "utils/ui"; export default function App({ Component, pageProps }: AppProps) { const router = useRouter(); @@ -118,15 +118,15 @@ export default function App({ Component, pageProps }: AppProps) { const showUpdateDialog = (update: AppUpdate) => { if (update.autoUpdatable) { - setDialogMessage(getUpdateReadyToInstallMessage(update)); + showMiniDialog(updateReadyToInstallDialogAttributes(update)); } else { setNotificationAttributes({ endIcon: , variant: "secondary", message: t("UPDATE_AVAILABLE"), onClick: () => - setDialogMessage( - getUpdateAvailableForDownloadMessage(update), + showMiniDialog( + updateAvailableForDownloadDialogAttributes(update), ), }); } diff --git a/web/apps/photos/src/utils/ui/index.tsx b/web/apps/photos/src/utils/ui/index.tsx index bfe8079f91..497948d52d 100644 --- a/web/apps/photos/src/utils/ui/index.tsx +++ b/web/apps/photos/src/utils/ui/index.tsx @@ -1,8 +1,4 @@ -import { ensureElectron } from "@/base/electron"; -import { AppUpdate } from "@/base/types/ipc"; -import { openURL } from "@/new/photos/utils/web"; import { DialogBoxAttributes } from "@ente/shared/components/DialogBox/types"; -import AutoAwesomeOutlinedIcon from "@mui/icons-material/AutoAwesomeOutlined"; import InfoOutlined from "@mui/icons-material/InfoRounded"; import { t } from "i18next"; import { Trans } from "react-i18next"; @@ -34,45 +30,6 @@ export const getTrashFileMessage = (deleteFileHelper): DialogBoxAttributes => ({ close: { text: t("cancel") }, }); -export const getUpdateReadyToInstallMessage = ({ - version, -}: AppUpdate): DialogBoxAttributes => ({ - icon: , - title: t("UPDATE_AVAILABLE"), - content: t("UPDATE_INSTALLABLE_MESSAGE"), - proceed: { - action: () => ensureElectron().updateAndRestart(), - text: t("INSTALL_NOW"), - variant: "accent", - }, - close: { - text: t("INSTALL_ON_NEXT_LAUNCH"), - variant: "secondary", - action: () => ensureElectron().updateOnNextRestart(version), - }, - staticBackdrop: true, -}); - -const downloadApp = () => openURL("https://ente.io/download/desktop"); - -export const getUpdateAvailableForDownloadMessage = ({ - version, -}: AppUpdate): DialogBoxAttributes => ({ - icon: , - title: t("UPDATE_AVAILABLE"), - content: t("UPDATE_AVAILABLE_MESSAGE"), - close: { - text: t("IGNORE_THIS_VERSION"), - variant: "secondary", - action: () => ensureElectron().skipAppUpdate(version), - }, - proceed: { - action: downloadApp, - text: t("DOWNLOAD_AND_INSTALL"), - variant: "accent", - }, -}); - export const getRootLevelFileWithFolderNotAllowMessage = (): DialogBoxAttributes => ({ icon: , diff --git a/web/packages/base/components/MiniDialog.tsx b/web/packages/base/components/MiniDialog.tsx index f3739e849a..df9549016b 100644 --- a/web/packages/base/components/MiniDialog.tsx +++ b/web/packages/base/components/MiniDialog.tsx @@ -36,11 +36,6 @@ export interface MiniDialogAttributes { * allow passing a i18next component. */ message?: React.ReactNode; - /** - * If `true`, then clicks in the backdrop are ignored. The default behaviour - * is to close the dialog when the background is clicked. - */ - staticBackdrop?: boolean; /** * If `true`, then the dialog cannot be closed (e.g. with the ESC key, or * clicking on the backdrop) except through one of the explicitly provided @@ -102,8 +97,17 @@ export interface MiniDialogAttributes { * Default is `t("cancel")`. * * Set this to `false` to omit the cancel button altogether. + * + * The object form allows providing both the button title and the action + * handler (synchronous). The dialog is always closed on clicks. */ - cancel?: string | false; + cancel?: + | string + | false + | { + text: string; + action: () => void; + }; } type MiniDialogProps = Omit & { @@ -138,6 +142,21 @@ export const AttributedMiniDialog: React.FC< resetPhaseAndClose(); }; + const [cancelTitle, handleCancel] = (( + c: MiniDialogAttributes["cancel"], + ) => { + if (c === false) return [undefined, undefined]; + if (c === undefined) return [t("cancel"), resetPhaseAndClose]; + if (typeof c == "string") return [c, resetPhaseAndClose]; + return [ + c.text, + () => { + resetPhaseAndClose(); + c.action(); + }, + ]; + })(attributes.cancel); + const { PaperProps, ...rest } = props; return ( @@ -212,13 +231,13 @@ export const AttributedMiniDialog: React.FC< {attributes.continue.text ?? t("ok")} )} - {attributes.cancel !== false && ( + {cancelTitle && ( - {attributes.cancel ?? t("cancel")} + {cancelTitle} )} diff --git a/web/packages/new/photos/components/utils/dialog.ts b/web/packages/new/photos/components/utils/dialog.ts deleted file mode 100644 index a2bb87a995..0000000000 --- a/web/packages/new/photos/components/utils/dialog.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; -import { openURL } from "@/new/photos/utils/web"; -import { t } from "i18next"; - -export const downloadAppDialogAttributes = (): MiniDialogAttributes => { - return { - title: t("download_app"), - message: t("download_app_message"), - - continue: { - text: t("download"), - action: downloadApp, - }, - cancel: t("close"), - }; -}; - -const downloadApp = () => openURL("https://ente.io/download/desktop"); diff --git a/web/packages/new/photos/components/utils/download.tsx b/web/packages/new/photos/components/utils/download.tsx new file mode 100644 index 0000000000..d26e41c10c --- /dev/null +++ b/web/packages/new/photos/components/utils/download.tsx @@ -0,0 +1,50 @@ +import type { MiniDialogAttributes } from "@/base/components/MiniDialog"; +import { ensureElectron } from "@/base/electron"; +import type { AppUpdate } from "@/base/types/ipc"; +import { openURL } from "@/new/photos/utils/web"; +import AutoAwesomeOutlined from "@mui/icons-material/AutoAwesomeOutlined"; +import { t } from "i18next"; + +export const downloadAppDialogAttributes = (): MiniDialogAttributes => ({ + title: t("download_app"), + message: t("download_app_message"), + continue: { + text: t("download"), + action: downloadApp, + }, +}); + +const downloadApp = () => openURL("https://ente.io/download/desktop"); + +export const updateReadyToInstallDialogAttributes = ({ + version, +}: AppUpdate): MiniDialogAttributes => ({ + title: t("UPDATE_AVAILABLE"), + message: t("UPDATE_INSTALLABLE_MESSAGE"), + icon: , + nonClosable: true, + continue: { + text: t("INSTALL_NOW"), + action: () => ensureElectron().updateAndRestart(), + }, + cancel: { + text: t("INSTALL_ON_NEXT_LAUNCH"), + action: () => ensureElectron().updateOnNextRestart(version), + }, +}); + +export const updateAvailableForDownloadDialogAttributes = ({ + version, +}: AppUpdate): MiniDialogAttributes => ({ + title: t("UPDATE_AVAILABLE"), + message: t("UPDATE_AVAILABLE_MESSAGE"), + icon: , + continue: { + text: t("DOWNLOAD_AND_INSTALL"), + action: downloadApp, + }, + cancel: { + text: t("IGNORE_THIS_VERSION"), + action: () => ensureElectron().skipAppUpdate(version), + }, +});