From f7c8a563a9c874877ced34963ec600c014253e5d Mon Sep 17 00:00:00 2001 From: Manav Rathi Date: Thu, 30 Jan 2025 19:32:31 +0530 Subject: [PATCH] [web] Match mobile behaviour for archived files in all --- web/packages/media/file.ts | 2 +- .../new/photos/components/gallery/reducer.ts | 116 ++++++++++++++---- web/packages/new/photos/services/files.ts | 2 +- 3 files changed, 92 insertions(+), 28 deletions(-) diff --git a/web/packages/media/file.ts b/web/packages/media/file.ts index 13a9cd8e7b..142e5a632f 100644 --- a/web/packages/media/file.ts +++ b/web/packages/media/file.ts @@ -150,7 +150,7 @@ export interface EncryptedEnteFile { * While the file ID is unique, we'd can still have multiple entries for each * file ID in our local state, one per collection IDs to which the file belongs. * That is, the uniqueness is across the (fileID, collectionID) pairs. See - * [Note: Collection Files]. + * [Note: Collection File]. */ export interface EnteFile extends Omit< diff --git a/web/packages/new/photos/components/gallery/reducer.ts b/web/packages/new/photos/components/gallery/reducer.ts index c74b6fe4e2..0f76028e8b 100644 --- a/web/packages/new/photos/components/gallery/reducer.ts +++ b/web/packages/new/photos/components/gallery/reducer.ts @@ -165,8 +165,29 @@ export interface GalleryState { defaultHiddenCollectionIDs: Set; /** * File IDs of the files that the user has hidden. + * + * Unlike archived files which can be in a mixture of normal and archived + * albums, hidden files can only be in hidden albums. */ hiddenFileIDs: Set; + /** + * File IDs of the files that the user has archived. + * + * Files can be individually archived (which is a file level property), or + * archived by virtue of being placed in an archived album (which is a + * collection file level property). + * + * Archived files are not supposed to be shown in the all section, + * irrespective of which of those two way they obtain their archive status. + * In particular, a (collection) file can be both in an archived album and + * an normal album, so just checking for membership in archived collections + * is not enough to filter them out from all. Instead, we need to compile a + * list of file IDs that have the archive status, and then filter the + * collection files using this list. + * + * For fast filtering, this is a set instead of a list. + */ + archivedFileIDs: Set; /** * File IDs of all the files that the user has marked as a favorite. * @@ -397,6 +418,7 @@ const initialGalleryState: GalleryState = { archivedCollectionIDs: new Set(), defaultHiddenCollectionIDs: new Set(), hiddenFileIDs: new Set(), + archivedFileIDs: new Set(), favoriteFileIDs: new Set(), allCollectionNameByID: new Map(), fileCollectionIDs: new Map(), @@ -428,9 +450,13 @@ const galleryReducer: React.Reducer = ( action.allCollections, isHiddenCollection, ); + const hiddenFileIDs = deriveHiddenFileIDs(action.hiddenFiles); const archivedCollectionIDs = deriveArchivedCollectionIDs(collections); - const hiddenFileIDs = deriveHiddenFileIDs(action.hiddenFiles); + const archivedFileIDs = deriveArchivedFileIDs( + archivedCollectionIDs, + action.files, + ); const view = { type: "albums" as const, activeCollectionSummaryID: ALL_SECTION, @@ -449,6 +475,7 @@ const galleryReducer: React.Reducer = ( defaultHiddenCollectionIDs: deriveDefaultHiddenCollectionIDs(hiddenCollections), hiddenFileIDs, + archivedFileIDs, favoriteFileIDs: deriveFavoriteFileIDs( collections, action.files, @@ -463,7 +490,7 @@ const galleryReducer: React.Reducer = ( collections, action.files, action.trashedFiles, - archivedCollectionIDs, + archivedFileIDs, ), hiddenCollectionSummaries: deriveHiddenCollectionSummaries( action.user, @@ -473,16 +500,21 @@ const galleryReducer: React.Reducer = ( view, }); } + case "setNormalCollections": { const collections = action.collections; const archivedCollectionIDs = deriveArchivedCollectionIDs(collections); + const archivedFileIDs = deriveArchivedFileIDs( + archivedCollectionIDs, + state.files, + ); const collectionSummaries = deriveCollectionSummaries( state.user!, collections, state.files, state.trashedFiles, - archivedCollectionIDs, + archivedFileIDs, ); // Revalidate the active view if needed. @@ -501,6 +533,7 @@ const galleryReducer: React.Reducer = ( ...state, collections, archivedCollectionIDs, + archivedFileIDs, favoriteFileIDs: deriveFavoriteFileIDs( collections, state.files, @@ -526,12 +559,16 @@ const galleryReducer: React.Reducer = ( const hiddenCollections = action.hiddenCollections; const archivedCollectionIDs = deriveArchivedCollectionIDs(collections); + const archivedFileIDs = deriveArchivedFileIDs( + archivedCollectionIDs, + state.files, + ); const collectionSummaries = deriveCollectionSummaries( state.user!, collections, state.files, state.trashedFiles, - archivedCollectionIDs, + archivedFileIDs, ); const hiddenCollectionSummaries = deriveHiddenCollectionSummaries( state.user!, @@ -565,6 +602,7 @@ const galleryReducer: React.Reducer = ( archivedCollectionIDs, defaultHiddenCollectionIDs: deriveDefaultHiddenCollectionIDs(hiddenCollections), + archivedFileIDs, favoriteFileIDs: deriveFavoriteFileIDs( collections, state.files, @@ -591,6 +629,10 @@ const galleryReducer: React.Reducer = ( return stateByUpdatingFilteredFiles({ ...state, files, + archivedFileIDs: deriveArchivedFileIDs( + state.archivedCollectionIDs, + files, + ), favoriteFileIDs: deriveFavoriteFileIDs( state.collections, files, @@ -602,7 +644,7 @@ const galleryReducer: React.Reducer = ( state.collections, files, state.trashedFiles, - state.archivedCollectionIDs, + state.archivedFileIDs, ), pendingSearchSuggestions: enqueuePendingSearchSuggestionsIfNeeded( @@ -622,6 +664,10 @@ const galleryReducer: React.Reducer = ( return stateByUpdatingFilteredFiles({ ...state, files, + archivedFileIDs: deriveArchivedFileIDs( + state.archivedCollectionIDs, + files, + ), favoriteFileIDs: deriveFavoriteFileIDs( state.collections, files, @@ -633,7 +679,7 @@ const galleryReducer: React.Reducer = ( state.collections, files, state.trashedFiles, - state.archivedCollectionIDs, + state.archivedFileIDs, ), pendingSearchSuggestions: enqueuePendingSearchSuggestionsIfNeeded( @@ -649,6 +695,10 @@ const galleryReducer: React.Reducer = ( return stateByUpdatingFilteredFiles({ ...state, files, + archivedFileIDs: deriveArchivedFileIDs( + state.archivedCollectionIDs, + files, + ), favoriteFileIDs: deriveFavoriteFileIDs( state.collections, files, @@ -662,7 +712,7 @@ const galleryReducer: React.Reducer = ( state.collections, files, state.trashedFiles, - state.archivedCollectionIDs, + state.archivedFileIDs, ), pendingSearchSuggestions: enqueuePendingSearchSuggestionsIfNeeded( @@ -717,7 +767,7 @@ const galleryReducer: React.Reducer = ( state.collections, state.files, action.trashedFiles, - state.archivedCollectionIDs, + state.archivedFileIDs, ), }); @@ -1000,6 +1050,23 @@ const deriveDefaultHiddenCollectionIDs = (hiddenCollections: Collection[]) => const deriveHiddenFileIDs = (hiddenFiles: EnteFile[]) => new Set(hiddenFiles.map((f) => f.id)); +/** + * Compute archived file IDs from their dependencies. + */ +const deriveArchivedFileIDs = ( + archivedCollectionIDs: Set, + files: EnteFile[], +) => + new Set( + files + .filter( + (file) => + isArchivedFile(file) || + archivedCollectionIDs.has(file.collectionID), + ) + .map((f) => f.id), + ); + /** * Compute favorite file IDs from their dependencies. */ @@ -1007,7 +1074,7 @@ const deriveFavoriteFileIDs = ( collections: Collection[], files: EnteFile[], unsyncedFavoriteUpdates: GalleryState["unsyncedFavoriteUpdates"], -): Set => { +) => { let favoriteFileIDs = new Set(); for (const collection of collections) { if (collection.type === CollectionType.favorites) { @@ -1034,7 +1101,7 @@ const deriveCollectionSummaries = ( collections: Collection[], files: EnteFile[], trashedFiles: EnteFile[], - archivedCollectionIDs: Set, + archivedFileIDs: Set, ) => { const collectionSummaries = createCollectionSummaries( user, @@ -1054,10 +1121,7 @@ const deriveCollectionSummaries = ( }); } - const allSectionFiles = findAllSectionVisibleFiles( - files, - archivedCollectionIDs, - ); + const allSectionFiles = findAllSectionVisibleFiles(files, archivedFileIDs); collectionSummaries.set(ALL_SECTION, { ...pseudoCollectionOptionsForFiles(allSectionFiles), id: ALL_SECTION, @@ -1247,15 +1311,8 @@ const isSharedOnlyViaLink = (collection: Collection) => */ const findAllSectionVisibleFiles = ( files: EnteFile[], - archivedCollectionIDs: Set, -) => - uniqueFilesByID( - files.filter( - (file) => - !isArchivedFile(file) && - !archivedCollectionIDs.has(file.collectionID), - ), - ); + archivedFileIDs: Set, +) => uniqueFilesByID(files.filter(({ id }) => !archivedFileIDs.has(id))); /** * Compute the {@link GalleryView} from its dependencies when we are switching @@ -1400,8 +1457,9 @@ const stateByUpdatingFilteredFiles = (state: GalleryState) => { const filteredFiles = deriveAlbumsFilteredFiles( state.files, state.trashedFiles, - state.archivedCollectionIDs, state.hiddenFileIDs, + state.archivedCollectionIDs, + state.archivedFileIDs, state.tempDeletedFileIDs, state.tempHiddenFileIDs, state.view, @@ -1433,8 +1491,9 @@ const stateByUpdatingFilteredFiles = (state: GalleryState) => { const deriveAlbumsFilteredFiles = ( files: GalleryState["files"], trashedFiles: GalleryState["trashedFiles"], - archivedCollectionIDs: GalleryState["archivedCollectionIDs"], hiddenFileIDs: GalleryState["hiddenFileIDs"], + archivedCollectionIDs: GalleryState["archivedCollectionIDs"], + archivedFileIDs: GalleryState["archivedFileIDs"], tempDeletedFileIDs: GalleryState["tempDeletedFileIDs"], tempHiddenFileIDs: GalleryState["tempHiddenFileIDs"], view: Extract, @@ -1474,8 +1533,13 @@ const deriveAlbumsFilteredFiles = ( return activeCollectionSummaryID === file.collectionID; } - // Show all remaining (non-hidden, non-archived) files in "All". if (activeCollectionSummaryID === ALL_SECTION) { + // Archived files (whether individually archived, or part of some + // archived album) should not be shown in "All". + if (archivedFileIDs.has(file.id)) { + return false; + } + // Show all remaining (non-hidden, non-archived) files in "All". return true; } diff --git a/web/packages/new/photos/services/files.ts b/web/packages/new/photos/services/files.ts index bca53f6132..0262e69803 100644 --- a/web/packages/new/photos/services/files.ts +++ b/web/packages/new/photos/services/files.ts @@ -193,7 +193,7 @@ export const sortFiles = (files: EnteFile[], sortAsc = false) => { }; /** - * [Note: Collection Files] + * [Note: Collection File] * * File IDs themselves are unique across all the files for the user (in fact, * they're unique across all the files in an Ente instance). However, we still