ontology
This commit is contained in:
@@ -79,7 +79,7 @@ import {
|
||||
useUserDetailsSnapshot,
|
||||
} from "ente-new/photos/components/utils/use-snapshot";
|
||||
import {
|
||||
CollectionSummaryID,
|
||||
PseudoCollectionID,
|
||||
type CollectionSummaries,
|
||||
} from "ente-new/photos/services/collection-summary";
|
||||
import exportService from "ente-new/photos/services/export";
|
||||
@@ -453,12 +453,12 @@ const ShortcutSection: React.FC<ShortcutSectionProps> = ({
|
||||
};
|
||||
|
||||
const openTrashSection = () => {
|
||||
galleryContext.setActiveCollectionID(CollectionSummaryID.trash);
|
||||
galleryContext.setActiveCollectionID(PseudoCollectionID.trash);
|
||||
onCloseSidebar();
|
||||
};
|
||||
|
||||
const openArchiveSection = () => {
|
||||
galleryContext.setActiveCollectionID(CollectionSummaryID.archiveItems);
|
||||
galleryContext.setActiveCollectionID(PseudoCollectionID.archiveItems);
|
||||
onCloseSidebar();
|
||||
};
|
||||
|
||||
@@ -482,7 +482,7 @@ const ShortcutSection: React.FC<ShortcutSectionProps> = ({
|
||||
<RowButton
|
||||
startIcon={<ArchiveOutlinedIcon />}
|
||||
label={t("section_archive")}
|
||||
caption={summaryCaption(CollectionSummaryID.archiveItems)}
|
||||
caption={summaryCaption(PseudoCollectionID.archiveItems)}
|
||||
onClick={openArchiveSection}
|
||||
/>
|
||||
<RowButton
|
||||
@@ -501,7 +501,7 @@ const ShortcutSection: React.FC<ShortcutSectionProps> = ({
|
||||
<RowButton
|
||||
startIcon={<DeleteOutlineIcon />}
|
||||
label={t("section_trash")}
|
||||
caption={summaryCaption(CollectionSummaryID.trash)}
|
||||
caption={summaryCaption(PseudoCollectionID.trash)}
|
||||
onClick={openTrashSection}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -922,9 +922,10 @@ const Page: React.FC = () => {
|
||||
onClose={handleCloseCollectionSelector}
|
||||
attributes={collectionSelectorAttributes}
|
||||
collectionSummaries={normalCollectionSummaries}
|
||||
collectionForCollectionID={(id) =>
|
||||
collectionForCollectionSummaryID={(id) =>
|
||||
// Null assert since the collection selector should only
|
||||
// show selectable normalCollectionSummaries.
|
||||
// show "selectable" normalCollectionSummaries. See:
|
||||
// [Note: Picking from selectable collection summaries].
|
||||
findCollectionCreatingUncategorizedIfNeeded(
|
||||
normalCollections,
|
||||
id,
|
||||
|
||||
@@ -70,18 +70,33 @@ type CollectionSelectorProps = ModalVisibilityProps & {
|
||||
attributes: CollectionSelectorAttributes | undefined;
|
||||
/**
|
||||
* The collections to list.
|
||||
*
|
||||
* The picker does not list all of the collection summaries, it filters
|
||||
* these provided list down to values which make sense for the
|
||||
* {@link attribute}'s {@link action}.
|
||||
*
|
||||
* See: [Note: Picking from selectable collection summaries].
|
||||
*/
|
||||
collectionSummaries: CollectionSummaries;
|
||||
/**
|
||||
* A function to map from a collection or pseudo-collection ID to a
|
||||
* {@link Collection}.
|
||||
* A function to map from a collection summary ID to a {@link Collection}.
|
||||
*
|
||||
* This is invoked when the user makes a selection, to convert the ID of the
|
||||
* selected collection, which can be a pseudo-collection too, into a
|
||||
* collection object that can be passed to the {@link callback} attribute of
|
||||
* {@link CollectionSelectorAttributes}.
|
||||
* selected collection summary into a collection object that can be passed
|
||||
* as the {@link callback} property of {@link CollectionSelectorAttributes}.
|
||||
*
|
||||
* [Note: Picking from selectable collection summaries]
|
||||
*
|
||||
* In general, not all pseudo collections can be converted into a
|
||||
* collection. For example, there is no underlying collection corresponding
|
||||
* to the "All" pseudo collection. However, the implementation of
|
||||
* {@link CollectionSelector} is such that it filters the provided
|
||||
* {@link collectionSummaries} to only show those which, when selected, can
|
||||
* be mapped to an (existing or on-demand created) collection.
|
||||
*/
|
||||
collectionForCollectionID: (collectionID: number) => Promise<Collection>;
|
||||
collectionForCollectionSummaryID: (
|
||||
collectionID: number,
|
||||
) => Promise<Collection>;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -93,7 +108,7 @@ export const CollectionSelector: React.FC<CollectionSelectorProps> = ({
|
||||
onClose,
|
||||
attributes,
|
||||
collectionSummaries,
|
||||
collectionForCollectionID,
|
||||
collectionForCollectionSummaryID,
|
||||
}) => {
|
||||
// Make the dialog fullscreen if the screen is <= the dialog's max width.
|
||||
const isFullScreen = useMediaQuery("(max-width: 490px)");
|
||||
@@ -150,8 +165,8 @@ export const CollectionSelector: React.FC<CollectionSelectorProps> = ({
|
||||
const { action, onSelectCollection, onCancel, onCreateCollection } =
|
||||
attributes;
|
||||
|
||||
const handleCollectionClick = async (collectionID: number) => {
|
||||
onSelectCollection(await collectionForCollectionID(collectionID));
|
||||
const handleCollectionSummaryClick = async (id: number) => {
|
||||
onSelectCollection(await collectionForCollectionSummaryID(id));
|
||||
onClose();
|
||||
};
|
||||
|
||||
@@ -178,10 +193,10 @@ export const CollectionSelector: React.FC<CollectionSelectorProps> = ({
|
||||
{t("create_albums")}
|
||||
</LargeTileCreateNewButton>
|
||||
{filteredCollections.map((collectionSummary) => (
|
||||
<CollectionButton
|
||||
<CollectionSummaryButton
|
||||
key={collectionSummary.id}
|
||||
collectionSummary={collectionSummary}
|
||||
onCollectionClick={handleCollectionClick}
|
||||
onClick={handleCollectionSummaryClick}
|
||||
/>
|
||||
))}
|
||||
</DialogContent_>
|
||||
@@ -210,19 +225,19 @@ const titleForAction = (action: CollectionSelectorAction) => {
|
||||
}
|
||||
};
|
||||
|
||||
interface CollectionButtonProps {
|
||||
interface CollectionSummaryButtonProps {
|
||||
collectionSummary: CollectionSummary;
|
||||
onCollectionClick: (collectionID: number) => void;
|
||||
onClick: (collectionSummaryID: number) => void;
|
||||
}
|
||||
|
||||
const CollectionButton: React.FC<CollectionButtonProps> = ({
|
||||
const CollectionSummaryButton: React.FC<CollectionSummaryButtonProps> = ({
|
||||
collectionSummary,
|
||||
onCollectionClick,
|
||||
onClick,
|
||||
}) => (
|
||||
<ItemCard
|
||||
TileComponent={LargeTileButton}
|
||||
coverFile={collectionSummary.coverFile}
|
||||
onClick={() => onCollectionClick(collectionSummary.id)}
|
||||
onClick={() => onClick(collectionSummary.id)}
|
||||
>
|
||||
<LargeTileTextOverlay>
|
||||
<Typography>{collectionSummary.name}</Typography>
|
||||
|
||||
@@ -16,7 +16,7 @@ import log from "ente-base/log";
|
||||
import type { Collection } from "ente-media/collection";
|
||||
import type { FamilyData } from "ente-new/photos/services/user-details";
|
||||
import { createUncategorizedCollection } from "../../services/collection";
|
||||
import { CollectionSummaryID } from "../../services/collection-summary";
|
||||
import { PseudoCollectionID } from "../../services/collection-summary";
|
||||
|
||||
/**
|
||||
* Ensure that the keys in local storage are not malformed by verifying that the
|
||||
@@ -40,17 +40,17 @@ export const validateKey = async () => {
|
||||
|
||||
/**
|
||||
* Return the {@link Collection} (from amongst {@link collections}) with the
|
||||
* given {@link collectionID}. As a special case, if collection ID is the ID of
|
||||
* the placeholder uncategorized collection, create a new uncategorized
|
||||
* collection and then return it.
|
||||
* given {@link collectionSummaryID}. As a special case, if the given
|
||||
* {@link collectionSummaryID} is the ID of the placeholder uncategorized
|
||||
* collection, create a new uncategorized collection and then return it.
|
||||
*/
|
||||
export const findCollectionCreatingUncategorizedIfNeeded = async (
|
||||
collections: Collection[],
|
||||
collectionID: number,
|
||||
collectionSummaryID: number,
|
||||
): Promise<Collection | undefined> =>
|
||||
collectionID == CollectionSummaryID.uncategorizedPlaceholder
|
||||
collectionSummaryID == PseudoCollectionID.uncategorizedPlaceholder
|
||||
? createUncategorizedCollection()
|
||||
: collections.find(({ id }) => id == collectionID);
|
||||
: collections.find(({ id }) => id == collectionSummaryID);
|
||||
|
||||
export const constructUserIDToEmailMap = (
|
||||
user: User,
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
TRASH_SECTION,
|
||||
} from "../../services/collection";
|
||||
import {
|
||||
CollectionSummaryID,
|
||||
PseudoCollectionID,
|
||||
type CollectionSummary,
|
||||
type CollectionSummaryType,
|
||||
} from "../../services/collection-summary";
|
||||
@@ -258,7 +258,7 @@ export interface GalleryState {
|
||||
*
|
||||
* This will be either the ID of the user's uncategorized collection, if one
|
||||
* has already been created, otherwise it will be the predefined
|
||||
* {@link CollectionSummaryID.uncategorizedPlaceholder}.
|
||||
* {@link PseudoCollectionID.uncategorizedPlaceholder}.
|
||||
*
|
||||
* See: [Note: Uncategorized placeholder]
|
||||
*/
|
||||
@@ -486,7 +486,7 @@ const initialGalleryState: GalleryState = {
|
||||
normalCollectionSummaries: new Map(),
|
||||
hiddenCollectionSummaries: new Map(),
|
||||
uncategorizedCollectionSummaryID:
|
||||
CollectionSummaryID.uncategorizedPlaceholder,
|
||||
PseudoCollectionID.uncategorizedPlaceholder,
|
||||
tempDeletedFileIDs: new Set(),
|
||||
tempHiddenFileIDs: new Set(),
|
||||
pendingFavoriteUpdates: new Set(),
|
||||
@@ -1368,7 +1368,7 @@ const deriveUncategorizedCollectionSummaryID = (
|
||||
normalCollections: Collection[],
|
||||
) =>
|
||||
normalCollections.find(({ type }) => type == "uncategorized")?.id ??
|
||||
CollectionSummaryID.uncategorizedPlaceholder;
|
||||
PseudoCollectionID.uncategorizedPlaceholder;
|
||||
|
||||
const createCollectionSummaries = (
|
||||
user: User,
|
||||
|
||||
@@ -19,29 +19,32 @@ export type CollectionSummaryType =
|
||||
* ID of the special {@link CollectionSummary} instances that are not backed by
|
||||
* a real {@link Collection}.
|
||||
*/
|
||||
export const CollectionSummaryID = {
|
||||
export const PseudoCollectionID = {
|
||||
/**
|
||||
* The "All" section.
|
||||
*
|
||||
* The default view when the user opens the gallery, showing the unique
|
||||
* non-hidden and non-archived files in their collections.
|
||||
* The "All" section is the default view when the user opens the gallery,
|
||||
* showing them all of their unique non-hidden and non-archived files.
|
||||
*/
|
||||
all: 0,
|
||||
/**
|
||||
* The items shown in the "Archive" section.
|
||||
* A pseudo-collection containing the individually archived files.
|
||||
*
|
||||
* It shows the files that the user has individually archived.
|
||||
* The archive items is a pseudo-collection consisting of all the files
|
||||
* which have been individually archived. It is what gets shown when the
|
||||
* user navigates to the "Archive" section.
|
||||
*/
|
||||
archiveItems: -1,
|
||||
/**
|
||||
* Trash
|
||||
* Trash.
|
||||
*
|
||||
* This shows files that are in the user's trash - files that have been
|
||||
* deleted, but have not yet been deleted permanently.
|
||||
* This pseudo-collection contains files that are in the user's trash -
|
||||
* files that have been deleted, but have not yet been deleted permanently.
|
||||
*/
|
||||
trash: -2,
|
||||
/**
|
||||
* A placeholder for the uncategorized collection used till it is empty.
|
||||
* A placeholder for the uncategorized collection until the real one comes
|
||||
* into existence.
|
||||
*
|
||||
* [Note: Uncategorized placeholder]
|
||||
*
|
||||
@@ -55,11 +58,13 @@ export const CollectionSummaryID = {
|
||||
*/
|
||||
uncategorizedPlaceholder: -3,
|
||||
/**
|
||||
* The default collection shown in the "Hidden" section.
|
||||
* A pseudo-collection containing the individually hidden files.
|
||||
*
|
||||
* It shows the files that the user has individually hidden; effectively, it
|
||||
* works as a merged combination of all of the user's "default hidden"
|
||||
* albums (See: Note: Multiple "default" hidden collections]).
|
||||
* The "Hidden items" is the default pseudo-collection shown in the "Hidden"
|
||||
* section. It consists of the files that the user has individually hidden.
|
||||
*
|
||||
* It is derived by merging all of the user's "default hidden" albums (See:
|
||||
* Note: Multiple "default" hidden collections]).
|
||||
*
|
||||
* In addition to this "Hidden items" pseudo-collection, the "Hidden"
|
||||
* section also shows other albums that were hidden.
|
||||
@@ -74,56 +79,56 @@ export const HIDDEN_ITEMS_SECTION = -4;
|
||||
export const ALL_SECTION = 0;
|
||||
|
||||
/**
|
||||
* A massaged version of a collection (real or placeholder) or a pseudo
|
||||
* "section" suitable for being directly shown in the UI.
|
||||
* A massaged version of a collection or a pseudo-collection suitable for being
|
||||
* directly shown in the UI.
|
||||
*
|
||||
* From one perspective, this can be thought of as a "CollectionOrSection":
|
||||
* i.e., a group of files listed together in the UI, with the files coming from
|
||||
* a real "collection" or some special "section". In the first case, the
|
||||
* underlying listing will be backed by a {@link Collection}, while in the
|
||||
* second case the files and other attributes comprising the listing will be
|
||||
* determined by the special case-specific rules for that particular section.
|
||||
* From one perspective, this can be thought of as a
|
||||
* "CollectionOrPseudoCollection": a group of files listed together in the UI,
|
||||
* with the files coming from a real "collection" or some special "section".
|
||||
*
|
||||
* Even when this is backed by a corresponding {@link Collection}, it adds some
|
||||
* extra attributes that make it easier and more efficient for the UI elements
|
||||
* to render this collection summary directly. From that perspective, this can
|
||||
* be thought of as a "UICollection".
|
||||
* - In the first case, the underlying listing will be backed by a
|
||||
* {@link Collection},
|
||||
*
|
||||
* - In the second case the files and other attributes comprising the listing
|
||||
* will be determined by the special case-specific rules for that particular
|
||||
* pseudo-collection.
|
||||
*
|
||||
* However, even when this is backed by a corresponding "real"
|
||||
* {@link Collection}, it adds some extra attributes that make it easier and
|
||||
* more efficient for the UI elements to render this collection summary
|
||||
* directly. So from that perspective, this can be also be thought of as a
|
||||
* "UICollection".
|
||||
*/
|
||||
export interface CollectionSummary {
|
||||
/**
|
||||
* The ID of the underlying {@link Collection}, or one of the predefined
|
||||
* {@link CollectionSummaryID}s for sections and other pseudo-collections.
|
||||
* {@link PseudoCollectionID}s.
|
||||
*/
|
||||
id: number;
|
||||
/**
|
||||
* The primary "UI" type for the collection or section or pseudo-collection.
|
||||
* The primary "UI" type for the collection or pseudo-collection.
|
||||
*
|
||||
* For newer code consider using {@link attributes} instead.
|
||||
*/
|
||||
type: CollectionSummaryType;
|
||||
/**
|
||||
* Various UI related attributes of the collection or section or
|
||||
* pseudo-collection.
|
||||
* Various UI related attributes of the collection or pseudo-collection.
|
||||
*
|
||||
* This is meant to replace {@link type} gradually. It defines various
|
||||
* attributes about the underlying file listing that this collection summary
|
||||
* stands for which the UI elements rendering the collection summary might
|
||||
* want to know.
|
||||
* ad-hoc "UI" attributes which make it easier and more efficient for the UI
|
||||
* elements to render the collection summary in the UI.
|
||||
*/
|
||||
attributes: CollectionSummaryType[];
|
||||
/**
|
||||
* The name of the collection or section or pseudo-collection surfaced in
|
||||
* the UI.
|
||||
* The name of the collection or pseudo-collection surfaced in the UI.
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* The newest file in the collection or section or pseudo-collection (if it
|
||||
* is not empty).
|
||||
* The newest file in the collection or pseudo-collection (if any).
|
||||
*/
|
||||
latestFile: EnteFile | undefined;
|
||||
/**
|
||||
* The file to show as the cover for the collection or section or
|
||||
* pseudo-collection.
|
||||
* The file to show as the cover for the collection or pseudo-collection.
|
||||
*
|
||||
* This can be one of
|
||||
* - A file explicitly chosen by the user.
|
||||
@@ -133,13 +138,13 @@ export interface CollectionSummary {
|
||||
coverFile: EnteFile | undefined;
|
||||
/**
|
||||
* The number of files in the underlying collection, or the number of files
|
||||
* that belong to this section or pseudo-collection.
|
||||
* computed to belong to the pseudo-collection.
|
||||
*/
|
||||
fileCount: number;
|
||||
/**
|
||||
* The time (epoch microseconds) when the collection was last updated. For
|
||||
* sections or pseudo-collections this will (usually) be the updation time
|
||||
* of the latest file that it contains.
|
||||
* pseudo-collections this will (usually) be the updation time of the latest
|
||||
* file that it contains.
|
||||
*/
|
||||
updationTime: number | undefined;
|
||||
order?: number;
|
||||
|
||||
Reference in New Issue
Block a user