From c60aed7f0f2b55099fcf9cc3392b7fd05ab8a894 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Tue, 1 Jul 2025 07:49:46 +0530 Subject: [PATCH] Notify elsewhere too --- web/apps/photos/src/pages/gallery.tsx | 14 ++++-- .../photos/components/SelectedFileOptions.tsx | 20 -------- .../new/photos/components/gallery/helpers.ts | 27 ++++++++--- .../components/utils/dialog-attributes.tsx | 48 +++++++++++++++++++ 4 files changed, 79 insertions(+), 30 deletions(-) create mode 100644 web/packages/new/photos/components/utils/dialog-attributes.tsx diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index fd77960b24..b769759678 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -666,24 +666,28 @@ const Page: React.FC = () => { (op: CollectionOp) => (selectedCollection: Collection) => { void (async () => { showLoadingBar(); + let notifyOthersFiles = false; try { setOpenCollectionSelector(false); const selectedFiles = getSelectedFiles( selected, filteredFiles, ); - const processableFiles = selectedFiles.filter( + const userFiles = selectedFiles.filter( (f) => f.ownerID == user.id, ); const sourceCollectionID = selected.collectionID; - if (processableFiles.length > 0) { + if (userFiles.length > 0) { await performCollectionOp( op, selectedCollection, - processableFiles, + userFiles, sourceCollectionID, ); } + // See: [Note: Add and move of non-user files] + notifyOthersFiles = + userFiles.length != selectedFiles.length; clearSelection(); await remotePull({ silent: true }); } catch (e) { @@ -691,6 +695,10 @@ const Page: React.FC = () => { } finally { hideLoadingBar(); } + + if (notifyOthersFiles) { + showMiniDialog(notifyOthersFilesDialogAttributes()); + } })(); }; diff --git a/web/packages/new/photos/components/SelectedFileOptions.tsx b/web/packages/new/photos/components/SelectedFileOptions.tsx index d05b291f77..5c56a18a71 100644 --- a/web/packages/new/photos/components/SelectedFileOptions.tsx +++ b/web/packages/new/photos/components/SelectedFileOptions.tsx @@ -50,26 +50,6 @@ interface SelectedFileOptionsProps { * * This will not be set if we are in the people section, or if we are * showing search results. - * - * TODO: Need to implement delete-equivalent from shared albums. - * - * Notes: - * - * - Delete action should not be enabled 3 selected (0 Yours). There should - * be separate remove action. - * - * - On remove, if the file and collection both belong to current user, we - * just use move api to existing or uncat collection. - * - * - Otherwise, we call /collections/v3/remove-files (when collection and - * file belong to different users). - * - * - Album owner can remove files of all other users from their collection. - * Particiapant (viewer/collaborator) can only remove files that belong to - * them. - * - * Also note that that user cannot delete files that are not owned by the - * user, even if they are in an album owned by the user. */ collectionSummary: CollectionSummary | undefined; /** diff --git a/web/packages/new/photos/components/gallery/helpers.ts b/web/packages/new/photos/components/gallery/helpers.ts index 952a6c1c71..b3d69197fc 100644 --- a/web/packages/new/photos/components/gallery/helpers.ts +++ b/web/packages/new/photos/components/gallery/helpers.ts @@ -66,37 +66,50 @@ export const findCollectionCreatingUncategorizedIfNeeded = async ( * @param selectedCollection The existing or new collection selected by the * user. This serves as the target of the operation. * - * @param selectedFiles The files selected by the user, on which the operation - * should be performed. + * @param selectedUserFiles The files selected by the user, on which the + * operation should be performed. Currently these need to all belong to the + * user. * * @param sourceCollectionID In the case of a "move", the operation is always * expected to happen in the context of an existing collection, which serves as * the source collection for the move. In such a case, the caller should provide * this argument, using the collection ID of the collection in which the * selection occurred. + * + * [Note: Add and move of non-user files] + * + * Currently, all {@link selectedUserFiles} need to belong to the user. This is + * because adds and move cannot be performed on remote across ownership + * boundaries directly. + * + * Enhancement: The mobile client has support for adding and moving such files. + * It does so by creating a copy, but using hash checks to avoid a copy if not + * needed. Implement these. This is a bit non-trivial since the mobile client + * then also adds various heuristics to omit the display of the "doubled" files + * in the all section etc. */ export const performCollectionOp = async ( op: CollectionOp, selectedCollection: Collection, - selectedFiles: EnteFile[], + selectedUserFiles: EnteFile[], sourceCollectionID: number | undefined, ): Promise => { switch (op) { case "add": - await addToCollection(selectedCollection, selectedFiles); + await addToCollection(selectedCollection, selectedUserFiles); break; case "move": await moveFromCollection( sourceCollectionID!, selectedCollection, - selectedFiles, + selectedUserFiles, ); break; case "restore": - await restoreToCollection(selectedCollection, selectedFiles); + await restoreToCollection(selectedCollection, selectedUserFiles); break; case "unhide": - await moveToCollection(selectedCollection, selectedFiles); + await moveToCollection(selectedCollection, selectedUserFiles); break; } }; diff --git a/web/packages/new/photos/components/utils/dialog-attributes.tsx b/web/packages/new/photos/components/utils/dialog-attributes.tsx new file mode 100644 index 0000000000..aaf1b3270f --- /dev/null +++ b/web/packages/new/photos/components/utils/dialog-attributes.tsx @@ -0,0 +1,48 @@ +import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; +import { Link } from "@mui/material"; +import type { MiniDialogAttributes } from "ente-base/components/MiniDialog"; +import { pt } from "ente-base/i18n"; +import { t } from "i18next"; +import { Trans } from "react-i18next"; + +export const confirmEnableMapsDialogAttributes = ( + onConfirm: () => void, +): MiniDialogAttributes => ({ + title: t("enable_maps_confirm"), + message: ( + + ), + }} + /> + ), + continue: { text: t("enable"), action: onConfirm }, +}); + +export const confirmDisableMapsDialogAttributes = ( + onConfirm: () => void, +): MiniDialogAttributes => ({ + title: t("disable_maps_confirm"), + message: , + continue: { text: t("disable"), color: "critical", action: onConfirm }, +}); + +/** + * Create attributes for a {@link MiniDialog} notifying the user that some of + * the files were not processed because they belonged to other users. + */ +export const notifyOthersFilesDialogAttributes = () => ({ + // TODO(RE): + title: pt("Note"), + icon: , + // TODO(RE): + message: pt("Files added by other users were not processed"), + cancel: t("ok"), +});