diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index 204252d36d..5f650b8949 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -1360,14 +1360,6 @@ const preloadImage = (imgBasePath: string) => { new Image().srcset = srcset.join(","); }; -const mergeMaps = (map1: Map, map2: Map) => { - const mergedMap = new Map(map1); - map2.forEach((value, key) => { - mergedMap.set(key, value); - }); - return mergedMap; -}; - type NormalNavbarContentsProps = SearchBarProps & { openSidebar: () => void; openUploader: () => void; diff --git a/web/apps/photos/src/services/collectionService.ts b/web/apps/photos/src/services/collectionService.ts index 0e1f5c75dc..98ff337c8f 100644 --- a/web/apps/photos/src/services/collectionService.ts +++ b/web/apps/photos/src/services/collectionService.ts @@ -339,54 +339,6 @@ export const getCollection = async ( } }; -export const getCollectionLatestFiles = ( - files: EnteFile[], -): CollectionToFileMap => { - const latestFiles = new Map(); - - files.forEach((file) => { - if (!latestFiles.has(file.collectionID)) { - latestFiles.set(file.collectionID, file); - } - }); - return latestFiles; -}; - -export const getCollectionCoverFiles = ( - files: EnteFile[], - collections: Collection[], -): CollectionToFileMap => { - const collectionIDToFileMap = groupFilesBasedOnCollectionID(files); - - const coverFiles = new Map(); - - collections.forEach((collection) => { - const collectionFiles = collectionIDToFileMap.get(collection.id); - if (!collectionFiles || collectionFiles.length === 0) { - return; - } - const coverID = collection.pubMagicMetadata?.data?.coverID; - if (typeof coverID === "number" && coverID > 0) { - const coverFile = collectionFiles.find( - (file) => file.id === coverID, - ); - if (coverFile) { - coverFiles.set(collection.id, coverFile); - return; - } - } - if (collection.pubMagicMetadata?.data?.asc) { - coverFiles.set( - collection.id, - collectionFiles[collectionFiles.length - 1], - ); - } else { - coverFiles.set(collection.id, collectionFiles[0]); - } - }); - return coverFiles; -}; - export const getFavItemIds = async ( files: EnteFile[], ): Promise> => { @@ -1107,34 +1059,6 @@ function compareCollectionsLatestFile(first: EnteFile, second: EnteFile) { } } -export function getDummyUncategorizedCollectionSummary(): CollectionSummary { - return { - id: DUMMY_UNCATEGORIZED_COLLECTION, - name: t("section_uncategorized"), - type: "uncategorized", - latestFile: null, - coverFile: null, - fileCount: 0, - updationTime: 0, - }; -} - - - -export function getTrashedCollectionSummary( - trashedFiles: EnteFile[], -): CollectionSummary { - return { - id: TRASH_SECTION, - name: t("section_trash"), - type: "trash", - coverFile: null, - latestFile: trashedFiles?.[0], - fileCount: trashedFiles?.length, - updationTime: trashedFiles?.[0]?.updationTime, - }; -} - export async function getUncategorizedCollection( collections?: Collection[], ): Promise { diff --git a/web/apps/photos/src/services/watch.ts b/web/apps/photos/src/services/watch.ts index edc9f1e36c..8b7dfceb10 100644 --- a/web/apps/photos/src/services/watch.ts +++ b/web/apps/photos/src/services/watch.ts @@ -20,7 +20,7 @@ import debounce from "debounce"; import uploadManager, { type UploadItemWithCollection, } from "services/upload/uploadManager"; -import { groupFilesBasedOnCollectionID } from "utils/file"; +import { groupFilesBasedOnCollectionID } from "@/new/photos/services/file"; import { removeFromCollection } from "./collectionService"; /** diff --git a/web/apps/photos/src/utils/file/index.ts b/web/apps/photos/src/utils/file/index.ts index 7a841779d3..48a0698df0 100644 --- a/web/apps/photos/src/utils/file/index.ts +++ b/web/apps/photos/src/utils/file/index.ts @@ -92,17 +92,6 @@ export async function downloadFile(file: EnteFile) { } } -/** Segment the given {@link files} into lists indexed by their collection ID */ -export const groupFilesBasedOnCollectionID = (files: EnteFile[]) => { - const result = new Map(); - for (const file of files) { - const id = file.collectionID; - if (!result.has(id)) result.set(id, []); - result.get(id).push(file); - } - return result; -}; - function getSelectedFileIds(selectedFiles: SelectedState) { const filesIDs: number[] = []; for (const [key, val] of Object.entries(selectedFiles)) { diff --git a/web/apps/photos/tests/upload.test.ts b/web/apps/photos/tests/upload.test.ts index 7dd604b0ae..e74b9f27b4 100644 --- a/web/apps/photos/tests/upload.test.ts +++ b/web/apps/photos/tests/upload.test.ts @@ -9,7 +9,7 @@ import { getMetadataJSONMapKeyForJSON, } from "services/upload/takeout"; import { getUserDetailsV2 } from "services/userService"; -import { groupFilesBasedOnCollectionID } from "utils/file"; +import { groupFilesBasedOnCollectionID } from "@/new/photos/services/file"; const DATE_TIME_PARSING_TEST_FILE_NAMES = [ { diff --git a/web/packages/media/collection.ts b/web/packages/media/collection.ts index 27e500dc7c..b1bea603d6 100644 --- a/web/packages/media/collection.ts +++ b/web/packages/media/collection.ts @@ -118,8 +118,6 @@ export interface collectionAttributes { pathDecryptionNonce?: string; } -export type CollectionToFileMap = Map; - export interface RemoveFromCollectionRequest { collectionID: number; fileIDs: number[]; diff --git a/web/packages/new/photos/components/gallery/reducer.ts b/web/packages/new/photos/components/gallery/reducer.ts index a83c270a34..90661ee815 100644 --- a/web/packages/new/photos/components/gallery/reducer.ts +++ b/web/packages/new/photos/components/gallery/reducer.ts @@ -1,12 +1,6 @@ +//TODO Review entire file +/* eslint-disable @typescript-eslint/no-unnecessary-condition */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ -/** - * @file code that really belongs to pages/gallery.tsx itself (or related - * files), but it written here in a separate file so that we can write in this - * package that has TypeScript strict mode enabled. - * - * Once the original gallery.tsx is strict mode, this code can be inlined back - * there. - */ import { CollectionType, type Collection } from "@/media/collection"; import type { EnteFile } from "@/media/file"; @@ -29,6 +23,7 @@ import type { CollectionSummary, CollectionSummaryType, } from "../../services/collection/ui"; +import { groupFilesBasedOnCollectionID } from "../../services/file"; import { isArchivedCollection, isArchivedFile, @@ -236,6 +231,7 @@ export function getCollectionSummaries( collectionSummaries.set(collection.id, { id: collection.id, name: CollectionSummaryItemName, + // @ts-expect-error TODO Review types latestFile: collectionLatestFiles.get(collection.id), coverFile: collectionCoverFiles.get(collection.id), fileCount: collectionFilesCount.get(collection.id) ?? 0, @@ -254,6 +250,58 @@ export function getCollectionSummaries( return collectionSummaries; } +export type CollectionToFileMap = Map; + +export const getCollectionLatestFiles = ( + files: EnteFile[], +): CollectionToFileMap => { + const latestFiles = new Map(); + + files.forEach((file) => { + if (!latestFiles.has(file.collectionID)) { + latestFiles.set(file.collectionID, file); + } + }); + return latestFiles; +}; + +export const getCollectionCoverFiles = ( + files: EnteFile[], + collections: Collection[], +): CollectionToFileMap => { + const collectionIDToFileMap = groupFilesBasedOnCollectionID(files); + + const coverFiles = new Map(); + + collections.forEach((collection) => { + const collectionFiles = collectionIDToFileMap.get(collection.id); + if (!collectionFiles || collectionFiles.length === 0) { + return; + } + const coverID = collection.pubMagicMetadata?.data?.coverID; + if (typeof coverID === "number" && coverID > 0) { + const coverFile = collectionFiles.find( + (file) => file.id === coverID, + ); + if (coverFile) { + coverFiles.set(collection.id, coverFile); + return; + } + } + if (collection.pubMagicMetadata?.data?.asc) { + coverFiles.set( + collection.id, + // @ts-expect-error TODO Review types + collectionFiles[collectionFiles.length - 1], + ); + } else { + // @ts-expect-error TODO Review types + coverFiles.set(collection.id, collectionFiles[0]); + } + }); + return coverFiles; +}; + export function isOutgoingShare(collection: Collection, user: User): boolean { return collection.owner.id === user.id && collection.sharees?.length > 0; } @@ -262,6 +310,20 @@ export function isSharedOnlyViaLink(collection: Collection) { return collection.publicURLs?.length && !collection.sharees?.length; } +export function getDummyUncategorizedCollectionSummary(): CollectionSummary { + return { + id: DUMMY_UNCATEGORIZED_COLLECTION, + name: t("section_uncategorized"), + type: "uncategorized", + // @ts-expect-error TODO Review types + latestFile: null, + // @ts-expect-error TODO Review types + coverFile: null, + fileCount: 0, + updationTime: 0, + }; +} + export function getHiddenItemsSummary( hiddenFiles: EnteFile[], hiddenCollections: Collection[], @@ -281,8 +343,10 @@ export function getHiddenItemsSummary( name: t("hidden_items"), type: "hiddenItems", coverFile: hiddenItems?.[0], + // @ts-expect-error TODO Review types latestFile: hiddenItems?.[0], fileCount: hiddenItems?.length, + // @ts-expect-error TODO Review types updationTime: hiddenItems?.[0]?.updationTime, }; } @@ -316,9 +380,12 @@ export function getArchivedSectionSummary( id: ARCHIVE_SECTION, name: t("section_archive"), type: "archive", + // @ts-expect-error TODO Review types coverFile: null, + // @ts-expect-error TODO Review types latestFile: archivedFiles?.[0], fileCount: archivedFiles?.length, + // @ts-expect-error TODO Review types updationTime: archivedFiles?.[0]?.updationTime, }; } @@ -336,8 +403,10 @@ function getAllSectionSummary( name: t("section_all"), type: "all", coverFile: allSectionFiles?.[0], + // @ts-expect-error TODO Review types latestFile: allSectionFiles?.[0], fileCount: allSectionFiles?.length || 0, + // @ts-expect-error TODO Review types updationTime: allSectionFiles?.[0]?.updationTime, }; } @@ -368,3 +437,28 @@ function getAllSectionVisibleFiles( ); return allSectionVisibleFiles; } + +export function getTrashedCollectionSummary( + trashedFiles: EnteFile[], +): CollectionSummary { + return { + id: TRASH_SECTION, + name: t("section_trash"), + type: "trash", + // @ts-expect-error TODO Review types + coverFile: null, + // @ts-expect-error TODO Review types + latestFile: trashedFiles?.[0], + fileCount: trashedFiles?.length, + // @ts-expect-error TODO Review types + updationTime: trashedFiles?.[0]?.updationTime, + }; +} + +const mergeMaps = (map1: Map, map2: Map) => { + const mergedMap = new Map(map1); + map2.forEach((value, key) => { + mergedMap.set(key, value); + }); + return mergedMap; +}; diff --git a/web/packages/new/photos/services/file.ts b/web/packages/new/photos/services/file.ts new file mode 100644 index 0000000000..b508a157d0 --- /dev/null +++ b/web/packages/new/photos/services/file.ts @@ -0,0 +1,13 @@ +import type { EnteFile } from "@/media/file"; + +/** Segment the given {@link files} into lists indexed by their collection ID */ +export const groupFilesBasedOnCollectionID = (files: EnteFile[]) => { + const result = new Map(); + for (const file of files) { + const id = file.collectionID; + if (!result.has(id)) result.set(id, []); + // @ts-expect-error TODO: Review types + result.get(id).push(file); + } + return result; +};