diff --git a/web/apps/photos/src/pages/gallery.tsx b/web/apps/photos/src/pages/gallery.tsx index 46b151ef22..914d305c3b 100644 --- a/web/apps/photos/src/pages/gallery.tsx +++ b/web/apps/photos/src/pages/gallery.tsx @@ -72,6 +72,8 @@ import { usePeopleStateSnapshot } from "ente-new/photos/components/utils/use-sna import { shouldShowWhatsNew } from "ente-new/photos/services/changelog"; import { ALL_SECTION, + createAlbum, + createUncategorizedCollection, DUMMY_UNCATEGORIZED_COLLECTION, } from "ente-new/photos/services/collection"; import { areOnlySystemCollections } from "ente-new/photos/services/collection/ui"; @@ -114,8 +116,6 @@ import { FileWithPath } from "react-dropzone"; import { Trans } from "react-i18next"; import { addToFavorites, - createAlbum, - createUnCategorizedCollection, removeFromFavorites, } from "services/collectionService"; import { uploadManager } from "services/upload-manager"; @@ -1342,7 +1342,7 @@ const findCollectionCreatingUncategorizedIfNeeded = async ( collectionID: number, ) => { if (collectionID == DUMMY_UNCATEGORIZED_COLLECTION) { - return await createUnCategorizedCollection(); + return await createUncategorizedCollection(); } else { return collections.find((c) => c.id === collectionID); } diff --git a/web/apps/photos/src/services/collectionService.ts b/web/apps/photos/src/services/collectionService.ts index 37cee1add1..394bed0668 100644 --- a/web/apps/photos/src/services/collectionService.ts +++ b/web/apps/photos/src/services/collectionService.ts @@ -2,17 +2,13 @@ import type { User } from "ente-accounts/services/user"; import { ensureLocalUser } from "ente-accounts/services/user"; import log from "ente-base/log"; import { apiURL } from "ente-base/origins"; -import { - Collection, - CollectionPrivateMagicMetadataData, - CollectionSubType, - type CollectionType, -} from "ente-media/collection"; +import { Collection } from "ente-media/collection"; import { EnteFile } from "ente-media/file"; -import { ItemVisibility } from "ente-media/file-metadata"; import { addToCollection, - createCollection2, + createDefaultHiddenCollection, + createFavoritesCollection, + createUncategorizedCollection, isDefaultHiddenCollection, moveToCollection, } from "ente-new/photos/services/collection"; @@ -33,25 +29,8 @@ import { getToken } from "ente-shared/storage/localStorage/helpers"; import { batch } from "ente-utils/array"; import { isValidMoveTarget } from "utils/collection"; -const uncategorizedCollectionName = "Uncategorized"; -const defaultHiddenCollectionName = ".hidden"; -const favoritesCollectionName = "Favorites"; - const REQUEST_BATCH_SIZE = 1000; -export const createAlbum = (albumName: string) => - createCollection(albumName, "album"); - -const createCollection = async ( - collectionName: string, - type: CollectionType, - magicMetadataProps?: CollectionPrivateMagicMetadataData, -): Promise => - createCollection2(collectionName, type, magicMetadataProps); - -export const createFavoritesCollection = () => - createCollection(favoritesCollectionName, "favorites"); - export const addToFavorites = async ( file: EnteFile, disableOldWorkaround?: boolean, @@ -179,7 +158,7 @@ export const removeUserFiles = async ( } let uncategorizedCollection = await getUncategorizedCollection(); if (!uncategorizedCollection) { - uncategorizedCollection = await createUnCategorizedCollection(); + uncategorizedCollection = await createUncategorizedCollection(); } await moveToCollection( sourceCollectionID, @@ -320,9 +299,6 @@ export async function getUncategorizedCollection( return uncategorizedCollection; } -export const createUnCategorizedCollection = () => - createCollection(uncategorizedCollectionName, "uncategorized"); - export async function getDefaultHiddenCollection(): Promise { const collections = await getLocalCollections("hidden"); const hiddenCollection = collections.find((collection) => @@ -332,12 +308,6 @@ export async function getDefaultHiddenCollection(): Promise { return hiddenCollection; } -const createDefaultHiddenCollection = () => - createCollection(defaultHiddenCollectionName, "album", { - subType: CollectionSubType.defaultHidden, - visibility: ItemVisibility.hidden, - }); - export async function moveToHiddenCollection(files: EnteFile[]) { try { let hiddenCollection = await getDefaultHiddenCollection(); diff --git a/web/apps/photos/src/utils/collection.ts b/web/apps/photos/src/utils/collection.ts index 0b94f497e2..1d9574e413 100644 --- a/web/apps/photos/src/utils/collection.ts +++ b/web/apps/photos/src/utils/collection.ts @@ -13,6 +13,7 @@ import { isIncomingShare, moveToCollection, restoreToCollection, + createAlbum, } from "ente-new/photos/services/collection"; import { getAllLocalCollections, @@ -25,7 +26,6 @@ import { import { safeDirectoryName } from "ente-new/photos/utils/native-fs"; import { getData } from "ente-shared/storage/localStorage"; import { - createAlbum, removeFromCollection, unhideToCollection, } from "services/collectionService"; diff --git a/web/packages/new/photos/services/collection.ts b/web/packages/new/photos/services/collection.ts index 8052814588..53af58da8a 100644 --- a/web/packages/new/photos/services/collection.ts +++ b/web/packages/new/photos/services/collection.ts @@ -45,45 +45,16 @@ import { ensureUserKeyPair, getPublicKey } from "./user"; */ const requestBatchSize = 1000; +const uncategorizedCollectionName = "Uncategorized"; +const defaultHiddenCollectionName = ".hidden"; +const favoritesCollectionName = "Favorites"; + export const ARCHIVE_SECTION = -1; export const TRASH_SECTION = -2; export const DUMMY_UNCATEGORIZED_COLLECTION = -3; export const HIDDEN_ITEMS_SECTION = -4; export const ALL_SECTION = 0; -/** - * Return true if this is a default hidden collection. - * - * See also: [Note: Multiple "default" hidden collections]. - */ -export const isDefaultHiddenCollection = (collection: Collection) => - collection.magicMetadata?.data.subType == CollectionSubType.defaultHidden; - -/** - * Extract the IDs of all the "default" hidden collections. - * - * [Note: Multiple "default" hidden collections]. - * - * Normally, there is only expected to be one such collection. But to provide - * clients laxity in synchronization, we don't enforce this and instead allow - * for multiple such default hidden collections to exist. - */ -export const findDefaultHiddenCollectionIDs = (collections: Collection[]) => - new Set( - collections - .filter(isDefaultHiddenCollection) - .map((collection) => collection.id), - ); - -/** - * Return true if this is a collection that the user doesn't own. - */ -export const isIncomingShare = (collection: Collection, user: User) => - collection.owner.id !== user.id; - -export const isHiddenCollection = (collection: Collection) => - collection.magicMetadata?.data.visibility === ItemVisibility.hidden; - export const DEFAULT_HIDDEN_COLLECTION_USER_FACING_NAME = "Hidden"; /** @@ -99,6 +70,17 @@ export const getCollectionUserFacingName = (collection: Collection) => { return collection.name; }; +/** + * Create a new album (a collection of type "album") on remote, and return its + * local representation. + * + * Remote only, does not modify local state. + * + * @param albumName The name to use for the new album. + */ +export const createAlbum = (albumName: string) => + createCollection(albumName, "album"); + /** * Create a new collection on remote, and return its local representation. * @@ -111,7 +93,7 @@ export const getCollectionUserFacingName = (collection: Collection) => { * @param magicMetadataData Optional metadata to use as the collection's private * mutable metadata when creating the new collection. */ -export const createCollection2 = async ( +const createCollection = async ( name: string, type: CollectionType, magicMetadataData?: CollectionPrivateMagicMetadataData, @@ -708,6 +690,81 @@ const putCollectionsShareeMagicMetadata = async ( }), ); +/** + * Create a new collection of type "favorites" for the user on remote, and + * return its local representation. + * + * Remote only, does not modify local state. + * + * Each user can have at most one collection of type "favorites" owned by them. + * While this function does not enforce the constraint locally, it will fail + * because remote will enforce the constraint and fail the request when we + * attempt to create a second collection of type "favorites". + */ +export const createFavoritesCollection = () => + createCollection(favoritesCollectionName, "favorites"); + +/** + * Create a new collection of type "uncategorized" for the user on remote, and + * return its local representation. + * + * Remote only, does not modify local state. + * + * Each user can have at most one collection of type "uncategorized" owned by + * them. While this function does not enforce the constraint locally, it will + * fail because remote will enforce the constraint and fail the request when we + * attempt to create a second collection of type "uncategorized". + */ +export const createUncategorizedCollection = () => + createCollection(uncategorizedCollectionName, "uncategorized"); + +/** + * Create a new collection with hidden visibility on remote, marking it as the + * default hidden collection, and return its local representation. + * + * Remote only, does not modify local state. + * + * See also: [Note: Multiple "default" hidden collections]. + */ +export const createDefaultHiddenCollection = () => + createCollection(defaultHiddenCollectionName, "album", { + subType: CollectionSubType.defaultHidden, + visibility: ItemVisibility.hidden, + }); + +/** + * Return true if the provided collection is the default hidden collection. + * + * See also: [Note: Multiple "default" hidden collections]. + */ +export const isDefaultHiddenCollection = (collection: Collection) => + collection.magicMetadata?.data.subType == CollectionSubType.defaultHidden; + +/** + * Extract the IDs of all the "default" hidden collections. + * + * [Note: Multiple "default" hidden collections]. + * + * Normally, there is only expected to be one such collection. But to provide + * clients laxity in synchronization, we don't enforce this and instead allow + * for multiple such default hidden collections to exist. + */ +export const findDefaultHiddenCollectionIDs = (collections: Collection[]) => + new Set( + collections + .filter(isDefaultHiddenCollection) + .map((collection) => collection.id), + ); + +/** + * Return true if this is a collection that the user doesn't own. + */ +export const isIncomingShare = (collection: Collection, user: User) => + collection.owner.id !== user.id; + +export const isHiddenCollection = (collection: Collection) => + collection.magicMetadata?.data.visibility === ItemVisibility.hidden; + /** * Share the provided collection with another Ente user. *