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),
+ },
+});