From a5f3085e0181cd96fd2142558ab35d0f8d676e25 Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Mon, 7 Jul 2025 10:57:59 +0530 Subject: [PATCH] + sidebar --- .../DownloadStatusNotifications.tsx | 6 +- web/apps/photos/src/components/Sidebar.tsx | 67 +++++----- web/apps/photos/src/pages/gallery.tsx | 120 ++++++++---------- 3 files changed, 96 insertions(+), 97 deletions(-) diff --git a/web/apps/photos/src/components/DownloadStatusNotifications.tsx b/web/apps/photos/src/components/DownloadStatusNotifications.tsx index 95be991e99..27a246f120 100644 --- a/web/apps/photos/src/components/DownloadStatusNotifications.tsx +++ b/web/apps/photos/src/components/DownloadStatusNotifications.tsx @@ -24,7 +24,11 @@ interface DownloadStatusNotificationsProps { onRemoveSaveGroup: (saveGroup: SaveGroup) => void; /** * Called when the collection summary with the given {@link collectionID} - * and "hidden" {@link attribute} should be shown. + * should be shown. If {@link isHiddenCollectionSummary} is set, then any + * reauthentication as appropriate before switching to the hidden section of + * the app is performed first. + * + * and hidden attribute should be shown. * * This is only relevant in the context of the photos app, and can be * omitted by the public albums app. See the documentation of diff --git a/web/apps/photos/src/components/Sidebar.tsx b/web/apps/photos/src/components/Sidebar.tsx index 5830d79014..ce9ae1c2ba 100644 --- a/web/apps/photos/src/components/Sidebar.tsx +++ b/web/apps/photos/src/components/Sidebar.tsx @@ -140,18 +140,23 @@ type SidebarProps = ModalVisibilityProps & { */ onShowPlanSelector: () => void; /** - * Called when the collection summary with the given - * {@link collectionSummaryID} should be shown. - */ - onShowCollectionSummary: (collectionSummaryID: number) => void; - /** - * Called when the hidden section should be shown. + * Called when the collection summary with the given {@link collectionID} + * should be shown. * - * This triggers the display of the dialog to authenticate the user, exactly - * as if {@link onAuthenticateUser} were called. Then, on successful - * authentication, the gallery will switch to the hidden section. + * @param collectionSummaryID The ID of the {@link CollectionSummary} to + * switch to. + * + * @param isHiddenCollectionSummary If `true`, then any reauthentication as + * appropriate before switching to the hidden section of the app is + * performed first before showing the collection summary. + * + * @return A promise that fullfills after any needed reauthentication has + * been peformed (The view transition might still be in progress). */ - onShowHiddenSection: () => Promise; + onShowCollectionSummary: ( + collectionSummaryID: number, + isHiddenCollectionSummary?: boolean, + ) => Promise; /** * Called when the export dialog should be shown. */ @@ -175,7 +180,6 @@ export const Sidebar: React.FC = ({ uncategorizedCollectionSummaryID, onShowPlanSelector, onShowCollectionSummary, - onShowHiddenSection, onShowExport, onAuthenticateUser, }) => ( @@ -189,7 +193,6 @@ export const Sidebar: React.FC = ({ normalCollectionSummaries, uncategorizedCollectionSummaryID, onShowCollectionSummary, - onShowHiddenSection, }} /> ; const ShortcutSection: React.FC = ({ @@ -469,25 +471,26 @@ const ShortcutSection: React.FC = ({ normalCollectionSummaries, uncategorizedCollectionSummaryID, onShowCollectionSummary, - onShowHiddenSection, }) => { - const openUncategorizedSection = () => { - onShowCollectionSummary(uncategorizedCollectionSummaryID); - onCloseSidebar(); - }; + const handleOpenUncategorizedSection = () => + void onShowCollectionSummary(uncategorizedCollectionSummaryID).then( + onCloseSidebar, + ); - const openTrashSection = () => { - onShowCollectionSummary(PseudoCollectionID.trash); - onCloseSidebar(); - }; + const handleOpenTrashSection = () => + void onShowCollectionSummary(PseudoCollectionID.trash).then( + onCloseSidebar, + ); - const openArchiveSection = () => { - onShowCollectionSummary(PseudoCollectionID.archiveItems); - onCloseSidebar(); - }; + const handleOpenArchiveSection = () => + void onShowCollectionSummary(PseudoCollectionID.archiveItems).then( + onCloseSidebar, + ); - const openHiddenSection = () => - void onShowHiddenSection().then(onCloseSidebar); + const handleOpenHiddenSection = () => + void onShowCollectionSummary(PseudoCollectionID.hiddenItems, true).then( + onCloseSidebar, + ); const summaryCaption = (summaryID: number) => normalCollectionSummaries.get(summaryID)?.fileCount.toString(); @@ -498,13 +501,13 @@ const ShortcutSection: React.FC = ({ startIcon={} label={t("section_uncategorized")} caption={summaryCaption(uncategorizedCollectionSummaryID)} - onClick={openUncategorizedSection} + onClick={handleOpenUncategorizedSection} /> } label={t("section_archive")} caption={summaryCaption(PseudoCollectionID.archiveItems)} - onClick={openArchiveSection} + onClick={handleOpenArchiveSection} /> } @@ -517,13 +520,13 @@ const ShortcutSection: React.FC = ({ }} /> } - onClick={openHiddenSection} + onClick={handleOpenHiddenSection} /> } label={t("section_trash")} caption={summaryCaption(PseudoCollectionID.trash)} - onClick={openTrashSection} + onClick={handleOpenTrashSection} /> ); diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index 08a75f4a67..fc32b99276 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -89,7 +89,6 @@ import { import { haveOnlySystemCollections, PseudoCollectionID, - type CollectionSummary, } from "ente-new/photos/services/collection-summary"; import exportService from "ente-new/photos/services/export"; import { updateFilesVisibility } from "ente-new/photos/services/file"; @@ -790,80 +789,74 @@ const Page: React.FC = () => { setUploadTypeSelectorIntent(intent ?? "upload"); }; - const handleShowCollectionSummaryWithID = ( - collectionSummaryID: number | undefined, - ) => { - // Trigger a pull of the latest data from remote when opening the trash. - // - // This is needed for a specific scenario: - // - // 1. User deletes a collection, selecting the option to delete files. - // 2. Museum acks, and then client does a trash pull. - // - // This trash pull will not contain the files that belonged to the - // collection that got deleted because the collection deletion is a - // asynchronous operation. - // - // So the user might not see the entry for the just deleted file if they - // were to go to the trash meanwhile (until the next pull happens). To - // avoid this, we trigger a trash pull whenever it is opened. - if (collectionSummaryID == PseudoCollectionID.trash) { - void remoteFilesPull(); - } + const handleShowCollectionSummaryWithID = useCallback( + (collectionSummaryID: number | undefined) => { + // Trigger a pull of the latest data from remote when opening the trash. + // + // This is needed for a specific scenario: + // + // 1. User deletes a collection, selecting the option to delete files. + // 2. Museum acks, and then client does a trash pull. + // + // This trash pull will not contain the files that belonged to the + // collection that got deleted because the collection deletion is a + // asynchronous operation. + // + // So the user might not see the entry for the just deleted file if they + // were to go to the trash meanwhile (until the next pull happens). To + // avoid this, we trigger a trash pull whenever it is opened. + if (collectionSummaryID == PseudoCollectionID.trash) { + void remoteFilesPull(); + } - dispatch({ type: "showCollectionSummary", collectionSummaryID }); - }; + dispatch({ type: "showCollectionSummary", collectionSummaryID }); + }, + [], + ); /** - * Switch to gallery view to show the {@link CollectionSummary}. + * Switch to gallery view to show a collection or pseudo-collection. * - * @param cs The {@link CollectionSummary} to show. - * If a {@link CollectionSummary} is not provided, show the "All" section. + * @param collectionSummaryID The ID of the {@link CollectionSummary} to + * show. If not provided, show the "All" section. * - * If the given {@link CollectionSummary} is hidden, first perform any - * reauthentication as would be needed for showing the hidden section in the - * app, and then shows the {@link CollectionSummary}. + * @param isHidden If `true`, then any reauthentication as appropriate + * before switching to the hidden section of the app is performed first + * before before switching to the relevant collection or pseudo-collection. */ - // TODO(RE): - // eslint-disable-next-line @typescript-eslint/no-unused-vars - const handleShowCollectionSummary = (cs: CollectionSummary | undefined) => { - if (cs?.attributes.has("hidden")) { - void handleShowHiddenSection().then(() => { - handleShowCollectionSummaryWithID(cs.id); - }); - } else { - handleShowCollectionSummaryWithID(cs.id); - } - }; - - /** - * A variant / reimplementation of {@link handleShowCollectionSummary} for - * use by the {@link DownloadStatusNotifications} component (which does not - * know about the {@link CollectionSummary} TypeScript type). - */ - const handleDownloadStatusNotificationsShowCollectionSummary = ( - collectionSummaryID: number | undefined, - isHiddenCollectionSummary: boolean | undefined, - ) => { - if (isHiddenCollectionSummary) { - void handleShowHiddenSection().then(() => { - handleShowCollectionSummaryWithID(collectionSummaryID); - }); - } else { + const showCollectionSummary = useCallback( + async ( + collectionSummaryID: number | undefined, + isHiddenCollectionSummary: boolean | undefined, + ) => { + if (isHiddenCollectionSummary) { + await authenticateUser(); + } handleShowCollectionSummaryWithID(collectionSummaryID); - } - }; + }, + [authenticateUser, handleShowCollectionSummaryWithID], + ); + + const handleSidebarShowCollectionSummary = showCollectionSummary; + + const handleDownloadStatusNotificationsShowCollectionSummary = useCallback( + ( + collectionSummaryID: number | undefined, + isHiddenCollectionSummary: boolean | undefined, + ) => { + void showCollectionSummary( + collectionSummaryID, + isHiddenCollectionSummary, + ); + }, + [showCollectionSummary], + ); const handleChangeBarMode = (mode: GalleryBarMode) => mode == "people" ? dispatch({ type: "showPeople" }) : dispatch({ type: "showAlbums" }); - const handleShowHiddenSection = useCallback( - () => authenticateUser().then(() => dispatch({ type: "showHidden" })), - [], - ); - const handleFileViewerToggleFavorite = useCallback( async (file: EnteFile) => { const fileID = file.id; @@ -1114,8 +1107,7 @@ const Page: React.FC = () => { state.uncategorizedCollectionSummaryID } onShowPlanSelector={showPlanSelector} - onShowCollectionSummary={handleShowCollectionSummaryWithID} - onShowHiddenSection={handleShowHiddenSection} + onShowCollectionSummary={handleSidebarShowCollectionSummary} onShowExport={showExport} onAuthenticateUser={authenticateUser} />