wip checkpoint

This commit is contained in:
Manav Rathi
2024-09-27 12:54:17 +05:30
parent 7a60b1e15e
commit 4e04739d54
3 changed files with 63 additions and 61 deletions

View File

@@ -16,7 +16,7 @@ import { UnidentifiedFaces } from "@/new/photos/components/PeopleList";
import { PhotoDateTimePicker } from "@/new/photos/components/PhotoDateTimePicker";
import { photoSwipeZIndex } from "@/new/photos/components/PhotoViewer";
import { tagNumericValue, type RawExifTags } from "@/new/photos/services/exif";
import { annotatedFaceIDsForFile, isMLEnabled } from "@/new/photos/services/ml";
import { annotatedFaceIDsForFile, AnnotatedFacesForFile, getAnnotatedFacesForFile, getFacesForFile, isMLEnabled } from "@/new/photos/services/ml";
import { EnteFile } from "@/new/photos/types/file";
import { formattedByteSize } from "@/new/photos/utils/units";
import CopyButton from "@ente/shared/components/CodeBlock/CopyButton";
@@ -98,6 +98,7 @@ export const FileInfo: React.FC<FileInfoProps> = ({
const [exifInfo, setExifInfo] = useState<ExifInfo | undefined>();
const [openRawExif, setOpenRawExif] = useState(false);
const [annotatedFaces, setAnnotatedFaces] = useState<AnnotatedFacesForFile | undefined>();
const location = useMemo(() => {
if (file) {
@@ -107,23 +108,19 @@ export const FileInfo: React.FC<FileInfoProps> = ({
return exif?.parsed?.location;
}, [file, exif]);
const [annotatedPeopleFaceIDs, otherFaceIDs] =
useMemoSingleThreaded(async () => {
if (!file) return [[], []];
const annotatedFaceIDs = await annotatedFaceIDsForFile(file);
return annotatedFaceIDs.reduce(
([people, other], item) => {
if (item[1]) {
people.push(item);
} else {
other.push(item[0]);
}
return [people, other];
},
[[], []],
);
useEffect(() => {
let didCancel = false;
void (async () => {
const result = await getAnnotatedFacesForFile(file);
!didCancel && setAnnotatedFaces(result);
})();
return () => { didCancel = true;}
}, [file]);
useEffect(() => {
setExifInfo(parseExifInfo(exif));
}, [exif]);
@@ -287,7 +284,8 @@ export const FileInfo: React.FC<FileInfoProps> = ({
{isMLEnabled() && (
<>
{/* TODO-Cluster <PhotoPeopleList file={file} /> */}
{annotatedFaces?.annotatedFaceIDs.length &&
// {/* TODO-Cluster <PhotoPeopleList file={file} /> */}
<UnidentifiedFaces enteFile={file} />
</>
)}

View File

@@ -1,12 +1,11 @@
import { useIsMobileWidth } from "@/base/hooks";
import { faceCrop, unidentifiedFaceIDs } from "@/new/photos/services/ml";
import { faceCrop, type AnnotatedFaceID } from "@/new/photos/services/ml";
import type { Person } from "@/new/photos/services/ml/people";
import type { EnteFile } from "@/new/photos/types/file";
import { Skeleton, Typography, styled } from "@mui/material";
import { t } from "i18next";
import React, { useEffect, useState } from "react";
import { UnstyledButton } from "./mui-custom";
import type { CGroup } from "../services/user-entity";
export interface SearchPeopleListProps {
people: Person[];
@@ -67,28 +66,21 @@ const SearchPeopleButton = styled(UnstyledButton)(
`,
);
export interface CGroupPeopleListProps {
export interface AnnotatedFacePeopleListProps {
annotatedFaceIDs: AnnotatedFaceID[];
/**
* List of cgroup people to show.
*
* The current types don't reflect this, but these are all guaranteed to be
* {@link Person}s with type "cgroup"
* Called when the user selects a face in the list.
*/
people: Person[];
/**
* Called when the user selects a person in the list.
*/
onSelectPerson: (person: Person) => void;
onSelectFace: (annotatedFaceID: AnnotatedFaceID) => void;
}
/**
* Show the list of faces in the given file that are not linked to a a specific
* cgroup ("people").
* Show the list of faces in the given file that are associated with a specific
* person.
*/
export const CGroupPeopleList: React.FC<SearchPeopleListProps> = ({
people,
onSelectPerson,
}) => {
export const AnnotatedFacePeopleList: React.FC<
AnnotatedFacePeopleListProps
> = ({ annotatedFaceIDs, onSelectFace }) => {
const isMobileWidth = useIsMobileWidth();
return (
<SearchPeopleContainer
@@ -182,21 +174,6 @@ export const UnidentifiedFaces: React.FC<UnidentifiedFacesProps> = ({
}) => {
const [faceIDs, setFaceIDs] = useState<string[]>([]);
useEffect(() => {
let didCancel = false;
const go = async () => {
const faceIDs = await unidentifiedFaceIDs(enteFile);
!didCancel && setFaceIDs(faceIDs);
};
void go();
return () => {
didCancel = true;
};
}, [enteFile]);
if (faceIDs.length == 0) return <></>;
return (

View File

@@ -592,18 +592,39 @@ export const clipMatches = (
): Promise<CLIPMatches | undefined> =>
worker().then((w) => w.clipMatches(searchPhrase));
/** A face ID annotated with the ID of the person to which it is associated. */
export interface AnnotatedFaceID {
faceID: string;
personID: string;
}
/**
* List of faces found in a file
*
* It is actually a pair of lists, one annotated by the person ids, and one with
* just the face ids.
*/
export interface AnnotatedFacesForFile {
/**
* A list of {@link AnnotatedFaceID}s for all faces in the file that are
* also associated with a {@link Person}.
*/
annotatedFaceIDs: AnnotatedFaceID[];
/* A list of the remaining face (ids). */
otherFaceIDs: string[];
}
/**
* Return the list of faces found in the given {@link enteFile}.
*
* Each item is returned as a (faceID, personID) tuple, where the faceID is the
* ID of the face, and the personID is the id of the corresponding person that
* this face is associated to (if any).
*/
export const annotatedFaceIDsForFile = async (
export const getAnnotatedFacesForFile = async (
enteFile: EnteFile,
): Promise<[string, string | undefined][]> => {
): Promise<AnnotatedFacesForFile> => {
const annotatedFaceIDs: AnnotatedFaceID[] = [];
const otherFaceIDs: string[] = [];
const index = await getFaceIndex(enteFile.id);
if (!index) return [];
if (!index) return { annotatedFaceIDs, otherFaceIDs };
const people = _state.peopleSnapshot ?? [];
@@ -620,10 +641,16 @@ export const annotatedFaceIDsForFile = async (
}
}
return index.faces.map(({ faceID }) => [
faceID,
faceIDToPersonID.get(faceID),
]);
for (const { faceID } of index.faces) {
const personID = faceIDToPersonID.get(faceID);
if (personID) {
annotatedFaceIDs.push({ faceID, personID });
} else {
otherFaceIDs.push(faceID);
}
}
return { annotatedFaceIDs, otherFaceIDs };
};
/**