From e87d596b4c0b171cddce0fe29ee94115b6339fc7 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 27 Feb 2025 17:07:58 +0530 Subject: [PATCH] fav 1 --- web/apps/photos/src/components/PhotoFrame.tsx | 1 + .../gallery/components/viewer/FileViewer.tsx | 29 +++- .../gallery/components/viewer/photoswipe.ts | 124 ++++++++++++------ 3 files changed, 108 insertions(+), 46 deletions(-) diff --git a/web/apps/photos/src/components/PhotoFrame.tsx b/web/apps/photos/src/components/PhotoFrame.tsx index ebbff43ad7..5bb808cce8 100644 --- a/web/apps/photos/src/components/PhotoFrame.tsx +++ b/web/apps/photos/src/components/PhotoFrame.tsx @@ -554,6 +554,7 @@ const PhotoFrame = ({ onTriggerSyncWithRemote={handleTriggerSyncWithRemote} onSaveEditedImageCopy={handleSaveEditedImageCopy} {...{ + favoriteFileIDs, fileCollectionIDs, allCollectionsNameByID, onSelectCollection, diff --git a/web/packages/gallery/components/viewer/FileViewer.tsx b/web/packages/gallery/components/viewer/FileViewer.tsx index d891c08cbe..01526a2c86 100644 --- a/web/packages/gallery/components/viewer/FileViewer.tsx +++ b/web/packages/gallery/components/viewer/FileViewer.tsx @@ -76,6 +76,13 @@ export type FileViewerProps = ModalVisibilityProps & { * If true then the viewer does not show controls for downloading the file. */ disableDownload?: boolean; + /** + * File IDs of all the files that the user has marked as a favorite. + * + * If this is not provided then the favorite toggle button will not be shown + * in the file actions. + */ + favoriteFileIDs?: Set; /** * Called when there was some update performed within the file viewer that * necessitates us to sync with remote again to fetch the latest updates. @@ -119,6 +126,7 @@ const FileViewer: React.FC = ({ files, initialIndex, disableDownload, + favoriteFileIDs, fileCollectionIDs, allCollectionsNameByID, onSelectCollection, @@ -162,14 +170,27 @@ const FileViewer: React.FC = ({ const handleAnnotate = useCallback( (file: EnteFile) => { + log.debug(() => ["viewer", { action: "annotate", file }]); const fileID = file.id; const isOwnFile = file.ownerID == user?.id; - const isEditableImage = fileIsEditableImage(file); - return { fileID, isOwnFile, isEditableImage }; + const isFavorite = favoriteFileIDs?.has(file.id); + const isEditableImage = onSaveEditedImageCopy + ? fileIsEditableImage(file) + : undefined; + return { fileID, isOwnFile, isFavorite, isEditableImage }; }, - [user], + [user, favoriteFileIDs, onSaveEditedImageCopy], ); + const handleToggleFavorite = useMemo(() => { + return favoriteFileIDs + ? (annotatedFile: FileViewerAnnotatedFile) => { + setActiveAnnotatedFile(annotatedFile); + console.log("handleToggleFavorite", annotatedFile); + } + : undefined; + }, [favoriteFileIDs]); + const handleViewInfo = useCallback( (annotatedFile: FileViewerAnnotatedFile) => { setActiveAnnotatedFile(annotatedFile); @@ -208,7 +229,6 @@ const FileViewer: React.FC = ({ return onSaveEditedImageCopy ? (annotatedFile: FileViewerAnnotatedFile) => { setActiveAnnotatedFile(annotatedFile); - setActiveFileExif(undefined); setOpenImageEditor(true); } : undefined; @@ -242,6 +262,7 @@ const FileViewer: React.FC = ({ disableDownload, onClose: handleClose, onAnnotate: handleAnnotate, + onToggleFavorite: handleToggleFavorite, onViewInfo: handleViewInfo, onEditImage: handleEditImage, }); diff --git a/web/packages/gallery/components/viewer/photoswipe.ts b/web/packages/gallery/components/viewer/photoswipe.ts index 0e53b70492..a40458c5f2 100644 --- a/web/packages/gallery/components/viewer/photoswipe.ts +++ b/web/packages/gallery/components/viewer/photoswipe.ts @@ -1,11 +1,11 @@ /* eslint-disable */ // @ts-nocheck +import { pt } from "@/base/i18n"; import log from "@/base/log"; import type { EnteFile } from "@/media/file"; import { FileType } from "@/media/file-type"; import { t } from "i18next"; -import { pt } from "@/base/i18n"; import { forgetExif, forgetExifForItemData, @@ -35,31 +35,6 @@ if (process.env.NEXT_PUBLIC_ENTE_WIP_PS5) { PhotoSwipe = require("./ps5/dist/photoswipe.esm.js").default; } -type FileViewerPhotoSwipeOptions = { - /** - * Called when the file viewer is closed. - */ - onClose: () => void; - /** - * Called whenever the slide changes to obtain the derived data for the file - * that is about to be displayed. - */ - onAnnotate: (file: EnteFile) => FileViewerFileAnnotation; - /** - * Called when the user activates the info action on a file. - */ - onViewInfo: (annotatedFile: FileViewerAnnotatedFile) => void; - /** - * Called when the user activates the edit action on an image. - * - * If this callback is not provided, then the edit button is never shown. If - * this callback is provided, then the visibility of the edit button is - * determined by the {@link isEditableImage} property of - * {@link FileViewerFileAnnotation} for the file. - */ - onEditImage?: (annotatedFile: FileViewerAnnotatedFile) => void; -} & Pick; - /** * Derived data for a file that is needed to display the file viewer controls * etc associated with the file. @@ -75,15 +50,59 @@ export interface FileViewerFileAnnotation { * `true` if this file is owned by the logged in user (if any). */ isOwnFile: boolean; + /** + * `true` if this file has been marked as a favorite by the user. + * + * It will not be provided if favorite functionality is not available. + * + * Otherwise it determines the toggle state of the toggle favorite button. + */ + isFavorite?: boolean; /** * `true` if this is an image which can be edited. * - * The edit button is shown when this is true. See also the + * It will not be provided if editing is not available. + * + * Otherwise the edit button is shown when this is true. See also the * {@link onEditImage} option for {@link FileViewerPhotoSwipe} constructor. */ - isEditableImage: boolean; + isEditableImage?: boolean; } +type FileViewerPhotoSwipeOptions = { + /** + * Called when the file viewer is closed. + */ + onClose: () => void; + /** + * Called whenever the slide changes to obtain the derived data for the file + * that is about to be displayed. + */ + onAnnotate: (file: EnteFile) => FileViewerFileAnnotation; + /** + * Called when the user activates the toggle favorite action on a file. + * + * If this callback is not provided, then the toggle favorite button is not + * shown. If this callback is provided, then the current toggle state of the + * favorite button is determined by the {@link isFavorite} property of + * {@link FileViewerFileAnnotation} for the file. + */ + onToggleFavorite?: (annotatedFile: FileViewerAnnotatedFile) => void; + /** + * Called when the user activates the info action on a file. + */ + onViewInfo: (annotatedFile: FileViewerAnnotatedFile) => void; + /** + * Called when the user activates the edit action on an image. + * + * If this callback is not provided, then the edit button is never shown. If + * this callback is provided, then the visibility of the edit button is + * determined by the {@link isEditableImage} property of + * {@link FileViewerFileAnnotation} for the file. + */ + onEditImage?: (annotatedFile: FileViewerAnnotatedFile) => void; +} & Pick; + /** * A file and its annotation, in a nice cosy box. */ @@ -159,6 +178,7 @@ export class FileViewerPhotoSwipe { disableDownload, onClose, onAnnotate, + onToggleFavorite, onViewInfo, onEditImage, }: FileViewerPhotoSwipeOptions) { @@ -416,14 +436,26 @@ export class FileViewerPhotoSwipe { }); }, }); - pswp.ui.registerElement({ - name: "info", - title: t("info"), - order: 16, - isButton: true, - html: createPSRegisterElementIconHTML("info"), - onClick: withCurrentAnnotatedFile(onViewInfo), - }); + + if (onToggleFavorite) { + pswp.ui.registerElement({ + name: "favorite", + title: t("favorite"), + order: 15, + isButton: true, + html: createPSRegisterElementIconHTML("favorite"), + onClick: withCurrentAnnotatedFile(onToggleFavorite), + onInit: (buttonElement, pswp) => { + // TODO: + // pswp.on("change", () => + // buttonElement.classList.toggle( + // "pswp--ui-visible", + // currentFileAnnotation().isFavorite, + // ), + // ); + }, + }); + } if (onEditImage) { pswp.ui.registerElement({ @@ -431,21 +463,29 @@ export class FileViewerPhotoSwipe { // TODO(PS): // title: t("edit_image"), title: pt("Edit image"), - order: 15, + order: 16, isButton: true, html: createPSRegisterElementIconHTML("edit"), onClick: withCurrentAnnotatedFile(onEditImage), onInit: (buttonElement, pswp) => { - pswp.on("change", () => { - const { annotation } = currentAnnotatedFile(); + pswp.on("change", () => buttonElement.classList.toggle( "pswp--ui-visible", - annotation.isEditableImage, - ); - }); + currentFileAnnotation().isEditableImage, + ), + ); }, }); } + + pswp.ui.registerElement({ + name: "info", + title: t("info"), + order: 17, + isButton: true, + html: createPSRegisterElementIconHTML("info"), + onClick: withCurrentAnnotatedFile(onViewInfo), + }); }); // Modify the default UI elements.