[web] Use reducer for gallery - Fin 7/7 (#3811)
This finishes the overall move for the time being, preparing the ground for the people related gallery tweaks that we need to make.
This commit is contained in:
@@ -20,9 +20,6 @@ import {
|
||||
SearchResultsHeader,
|
||||
} from "@/new/photos/components/gallery";
|
||||
import {
|
||||
deriveAlbumishFilteredFiles,
|
||||
derivePeopleFilteredFiles,
|
||||
deriveTrashFilteredFiles,
|
||||
uniqueFilesByID,
|
||||
useGalleryReducer,
|
||||
type GalleryBarMode,
|
||||
@@ -32,7 +29,6 @@ import { shouldShowWhatsNew } from "@/new/photos/services/changelog";
|
||||
import {
|
||||
ALL_SECTION,
|
||||
DUMMY_UNCATEGORIZED_COLLECTION,
|
||||
TRASH_SECTION,
|
||||
isHiddenCollection,
|
||||
} from "@/new/photos/services/collection";
|
||||
import { areOnlySystemCollections } from "@/new/photos/services/collection/ui";
|
||||
@@ -306,15 +302,7 @@ export default function Gallery() {
|
||||
const collections = state.collections;
|
||||
const files = state.files;
|
||||
const hiddenFiles = state.hiddenFiles;
|
||||
const trashedFiles = state.trashedFiles;
|
||||
const archivedCollectionIDs = state.archivedCollectionIDs;
|
||||
const hiddenFileIDs = state.hiddenFileIDs;
|
||||
const collectionNameMap = state.allCollectionNameByID;
|
||||
const fileToCollectionsMap = state.fileCollectionIDs;
|
||||
const collectionSummaries = state.collectionSummaries;
|
||||
const hiddenCollectionSummaries = state.hiddenCollectionSummaries;
|
||||
const tempDeletedFileIDs = state.tempDeletedFileIDs;
|
||||
const tempHiddenFileIDs = state.tempHiddenFileIDs;
|
||||
const barMode = state.view?.type ?? "albums";
|
||||
const activeCollectionID =
|
||||
state.view?.type == "people"
|
||||
@@ -328,7 +316,7 @@ export default function Gallery() {
|
||||
const isInSearchMode = state.isInSearchMode;
|
||||
const filteredFiles = state.filteredFiles;
|
||||
|
||||
if (process.env.NEXT_PUBLIC_ENTE_WIP_CL) console.log("render", { state });
|
||||
if (process.env.NEXT_PUBLIC_ENTE_WIP_CL) console.log("render", state);
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
@@ -483,51 +471,13 @@ export default function Gallery() {
|
||||
|
||||
// TODO: Make this a normal useEffect.
|
||||
useMemoSingleThreaded(async () => {
|
||||
if (
|
||||
!files ||
|
||||
!user ||
|
||||
!trashedFiles ||
|
||||
!hiddenFiles ||
|
||||
!archivedCollectionIDs
|
||||
) {
|
||||
dispatch({
|
||||
type: "setFilteredFiles",
|
||||
filteredFiles: [],
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
let filteredFiles: EnteFile[];
|
||||
if (selectedSearchOption) {
|
||||
filteredFiles = await filterSearchableFiles(
|
||||
const searchResults = await filterSearchableFiles(
|
||||
selectedSearchOption.suggestion,
|
||||
);
|
||||
} else if (state.view?.type == "people") {
|
||||
filteredFiles = derivePeopleFilteredFiles(state, state.view);
|
||||
} else if (activeCollectionID === TRASH_SECTION) {
|
||||
filteredFiles = deriveTrashFilteredFiles(state);
|
||||
} else {
|
||||
filteredFiles = deriveAlbumishFilteredFiles(state);
|
||||
dispatch({ type: "setSearchResults", searchResults });
|
||||
}
|
||||
|
||||
dispatch({
|
||||
type: "setFilteredFiles",
|
||||
filteredFiles,
|
||||
});
|
||||
}, [
|
||||
barMode,
|
||||
files,
|
||||
trashedFiles,
|
||||
hiddenFiles,
|
||||
tempDeletedFileIDs,
|
||||
tempHiddenFileIDs,
|
||||
hiddenFileIDs,
|
||||
selectedSearchOption,
|
||||
activeCollectionID,
|
||||
archivedCollectionIDs,
|
||||
peopleState,
|
||||
activePersonID,
|
||||
]);
|
||||
}, [selectedSearchOption]);
|
||||
|
||||
const selectAll = (e: KeyboardEvent) => {
|
||||
// ignore ctrl/cmd + a if the user is typing in a text field
|
||||
@@ -923,8 +873,8 @@ export default function Gallery() {
|
||||
[],
|
||||
);
|
||||
|
||||
if (!user || !filteredFiles) {
|
||||
// Don't render until we get the logged in user and dispatch "mount".
|
||||
if (!user) {
|
||||
// Don't render until we dispatch "mount" with the logged in user.
|
||||
return <div></div>;
|
||||
}
|
||||
|
||||
@@ -1046,7 +996,8 @@ export default function Gallery() {
|
||||
activeCollection,
|
||||
activeCollectionID,
|
||||
setActiveCollectionID: handleSetActiveCollectionID,
|
||||
hiddenCollectionSummaries,
|
||||
hiddenCollectionSummaries:
|
||||
state.hiddenCollectionSummaries,
|
||||
showPeopleSectionButton,
|
||||
people:
|
||||
(state.view.type == "people"
|
||||
@@ -1129,8 +1080,8 @@ export default function Gallery() {
|
||||
activeCollectionID={activeCollectionID}
|
||||
activePersonID={activePerson?.id}
|
||||
enableDownload={true}
|
||||
fileToCollectionsMap={fileToCollectionsMap}
|
||||
collectionNameMap={collectionNameMap}
|
||||
fileToCollectionsMap={state.fileCollectionIDs}
|
||||
collectionNameMap={state.allCollectionNameByID}
|
||||
showAppDownloadBanner={
|
||||
files.length < 30 && !isInSearchMode
|
||||
}
|
||||
@@ -1185,7 +1136,7 @@ export default function Gallery() {
|
||||
<ExportModal
|
||||
show={exportModalView}
|
||||
onHide={closeExportModal}
|
||||
collectionNameMap={collectionNameMap}
|
||||
collectionNameMap={state.allCollectionNameByID}
|
||||
/>
|
||||
<AuthenticateUserModal
|
||||
open={authenticateUserModalView}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { searchOptionsForString } from "@/new/photos/services/search";
|
||||
import type { SearchOption } from "@/new/photos/services/search/types";
|
||||
import { nullToUndefined } from "@/utils/transform";
|
||||
import CalendarIcon from "@mui/icons-material/CalendarMonth";
|
||||
import ChevronRightIcon from "@mui/icons-material/ChevronRight";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import ImageIcon from "@mui/icons-material/Image";
|
||||
import LocationIcon from "@mui/icons-material/LocationOn";
|
||||
@@ -425,12 +424,7 @@ const EmptyState: React.FC<Pick<SearchBarProps, "onSelectPerson">> = ({
|
||||
|
||||
const SearchPeopleHeader: React.FC<ButtonishProps> = ({ onClick }) => (
|
||||
<SearchPeopleHeaderButton {...{ onClick }}>
|
||||
<Stack direction="row" color="text.muted">
|
||||
<Typography color="text.base" variant="large">
|
||||
{t("people")}
|
||||
</Typography>
|
||||
<ChevronRightIcon />
|
||||
</Stack>
|
||||
<Typography color="text.muted">{t("people")}</Typography>
|
||||
</SearchPeopleHeaderButton>
|
||||
);
|
||||
|
||||
|
||||
@@ -80,8 +80,9 @@ export type GalleryView =
|
||||
/**
|
||||
* The list of people to show in the gallery bar.
|
||||
*
|
||||
* Note that this can be different from the underlying list of people,
|
||||
* and can temporarily include a person from outside that list.
|
||||
* Note that this can be different from the underlying list of
|
||||
* visiblePeople in the {@link peopleState}, and can temporarily
|
||||
* include a person from outside that list.
|
||||
*/
|
||||
visiblePeople: Person[];
|
||||
/**
|
||||
@@ -236,6 +237,14 @@ export interface GalleryState {
|
||||
* possible) on switching back.
|
||||
*/
|
||||
selectedPersonID: string | undefined;
|
||||
/**
|
||||
* If present, this person is tacked on the the list of visible people
|
||||
* temporarily (until the user switches out from the people view).
|
||||
*
|
||||
* This is needed to retain a usually non-visible but temporarily selected
|
||||
* person in the people bar until the user switches to some other view.
|
||||
*/
|
||||
extraVisiblePerson: Person | undefined;
|
||||
/**
|
||||
* List of files that match the selected search option.
|
||||
*
|
||||
@@ -265,12 +274,15 @@ export interface GalleryState {
|
||||
*
|
||||
* That is, {@link isInSearchMode} may be true even when
|
||||
* {@link searchResults} is undefined.
|
||||
*
|
||||
* We will be _showing_ search results if both {@link isInSearchMode} is
|
||||
* `true` and {@link searchResults} is defined.
|
||||
*/
|
||||
isInSearchMode: boolean;
|
||||
/**
|
||||
* The files to show, uniqued and sorted appropriately.
|
||||
*/
|
||||
filteredFiles: EnteFile[] | undefined;
|
||||
filteredFiles: EnteFile[];
|
||||
}
|
||||
|
||||
export type GalleryAction =
|
||||
@@ -312,10 +324,9 @@ export type GalleryAction =
|
||||
}
|
||||
| { type: "showPeople" }
|
||||
| { type: "showPerson"; personID: string }
|
||||
| { type: "searchResults"; searchResults: EnteFile[] }
|
||||
| { type: "setSearchResults"; searchResults: EnteFile[] }
|
||||
| { type: "enterSearchMode" }
|
||||
| { type: "exitSearch" }
|
||||
| { type: "setFilteredFiles"; filteredFiles: EnteFile[] };
|
||||
| { type: "exitSearch" };
|
||||
|
||||
const initialGalleryState: GalleryState = {
|
||||
user: undefined,
|
||||
@@ -338,9 +349,10 @@ const initialGalleryState: GalleryState = {
|
||||
tempHiddenFileIDs: new Set<number>(),
|
||||
selectedCollectionSummaryID: undefined,
|
||||
selectedPersonID: undefined,
|
||||
extraVisiblePerson: undefined,
|
||||
searchResults: undefined,
|
||||
view: undefined,
|
||||
filteredFiles: undefined,
|
||||
filteredFiles: [],
|
||||
isInSearchMode: false,
|
||||
};
|
||||
|
||||
@@ -357,6 +369,12 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
);
|
||||
const archivedCollectionIDs =
|
||||
deriveArchivedCollectionIDs(collections);
|
||||
const hiddenFileIDs = deriveHiddenFileIDs(action.hiddenFiles);
|
||||
const view = {
|
||||
type: "albums" as const,
|
||||
activeCollectionSummaryID: ALL_SECTION,
|
||||
activeCollection: undefined,
|
||||
};
|
||||
return {
|
||||
...state,
|
||||
user: action.user,
|
||||
@@ -369,7 +387,7 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
archivedCollectionIDs,
|
||||
defaultHiddenCollectionIDs:
|
||||
deriveDefaultHiddenCollectionIDs(hiddenCollections),
|
||||
hiddenFileIDs: deriveHiddenFileIDs(action.hiddenFiles),
|
||||
hiddenFileIDs,
|
||||
favoriteFileIDs: deriveFavoriteFileIDs(
|
||||
collections,
|
||||
action.files,
|
||||
@@ -390,18 +408,23 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
hiddenCollections,
|
||||
action.hiddenFiles,
|
||||
),
|
||||
view: {
|
||||
type: "albums",
|
||||
activeCollectionSummaryID: ALL_SECTION,
|
||||
activeCollection: undefined,
|
||||
},
|
||||
view,
|
||||
filteredFiles: deriveAlbumsFilteredFiles(
|
||||
action.files,
|
||||
action.trashedFiles,
|
||||
archivedCollectionIDs,
|
||||
hiddenFileIDs,
|
||||
state.tempDeletedFileIDs,
|
||||
state.tempHiddenFileIDs,
|
||||
view,
|
||||
),
|
||||
};
|
||||
}
|
||||
case "setNormalCollections": {
|
||||
const archivedCollectionIDs = deriveArchivedCollectionIDs(
|
||||
action.collections,
|
||||
);
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
collections: action.collections,
|
||||
archivedCollectionIDs,
|
||||
@@ -419,13 +442,13 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
state.trashedFiles,
|
||||
archivedCollectionIDs,
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
case "setAllCollections": {
|
||||
const archivedCollectionIDs = deriveArchivedCollectionIDs(
|
||||
action.collections,
|
||||
);
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
collections: action.collections,
|
||||
hiddenCollections: action.hiddenCollections,
|
||||
@@ -452,11 +475,11 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
action.hiddenCollections,
|
||||
state.hiddenFiles,
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
case "setFiles": {
|
||||
const files = sortFiles(mergeMetadata(action.files));
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
files,
|
||||
favoriteFileIDs: deriveFavoriteFileIDs(
|
||||
@@ -471,7 +494,7 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
state.trashedFiles,
|
||||
state.archivedCollectionIDs,
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
case "fetchFiles": {
|
||||
const files = sortFiles(
|
||||
@@ -479,7 +502,7 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
getLatestVersionFiles([...state.files, ...action.files]),
|
||||
),
|
||||
);
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
files,
|
||||
favoriteFileIDs: deriveFavoriteFileIDs(
|
||||
@@ -494,11 +517,11 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
state.trashedFiles,
|
||||
state.archivedCollectionIDs,
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
case "uploadFile": {
|
||||
const files = sortFiles([...state.files, action.file]);
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
files,
|
||||
favoriteFileIDs: deriveFavoriteFileIDs(
|
||||
@@ -515,11 +538,11 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
state.trashedFiles,
|
||||
state.archivedCollectionIDs,
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
case "setHiddenFiles": {
|
||||
const hiddenFiles = sortFiles(mergeMetadata(action.hiddenFiles));
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingHiddenAlbums({
|
||||
...state,
|
||||
hiddenFiles,
|
||||
hiddenFileIDs: deriveHiddenFileIDs(hiddenFiles),
|
||||
@@ -528,7 +551,7 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
state.hiddenCollections,
|
||||
hiddenFiles,
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
case "fetchHiddenFiles": {
|
||||
const hiddenFiles = sortFiles(
|
||||
@@ -539,7 +562,7 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
]),
|
||||
),
|
||||
);
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingHiddenAlbums({
|
||||
...state,
|
||||
hiddenFiles,
|
||||
hiddenFileIDs: deriveHiddenFileIDs(hiddenFiles),
|
||||
@@ -548,10 +571,10 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
state.hiddenCollections,
|
||||
hiddenFiles,
|
||||
),
|
||||
};
|
||||
});
|
||||
}
|
||||
case "setTrashedFiles":
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
trashedFiles: action.trashedFiles,
|
||||
collectionSummaries: deriveCollectionSummaries(
|
||||
@@ -561,55 +584,63 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
action.trashedFiles,
|
||||
state.archivedCollectionIDs,
|
||||
),
|
||||
};
|
||||
});
|
||||
case "setPeopleState":
|
||||
return { ...state, peopleState: action.peopleState };
|
||||
case "markTempDeleted":
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbumsOrHiddenAlbums({
|
||||
...state,
|
||||
tempDeletedFileIDs: new Set(
|
||||
[...state.tempDeletedFileIDs].concat(
|
||||
action.files.map((f) => f.id),
|
||||
),
|
||||
),
|
||||
};
|
||||
});
|
||||
case "clearTempDeleted":
|
||||
return { ...state, tempDeletedFileIDs: new Set() };
|
||||
return refreshingFilteredFilesIfShowingAlbumsOrHiddenAlbums({
|
||||
...state,
|
||||
tempDeletedFileIDs: new Set(),
|
||||
});
|
||||
case "markTempHidden":
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
tempHiddenFileIDs: new Set(
|
||||
[...state.tempHiddenFileIDs].concat(
|
||||
action.files.map((f) => f.id),
|
||||
),
|
||||
),
|
||||
};
|
||||
});
|
||||
case "clearTempHidden":
|
||||
return { ...state, tempHiddenFileIDs: new Set() };
|
||||
case "showAll":
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
tempHiddenFileIDs: new Set(),
|
||||
});
|
||||
case "showAll":
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
searchResults: undefined,
|
||||
selectedCollectionSummaryID: undefined,
|
||||
extraVisiblePerson: undefined,
|
||||
searchResults: undefined,
|
||||
view: {
|
||||
type: "albums",
|
||||
activeCollectionSummaryID: ALL_SECTION,
|
||||
activeCollection: undefined,
|
||||
},
|
||||
isInSearchMode: false,
|
||||
};
|
||||
});
|
||||
case "showHidden":
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingHiddenAlbums({
|
||||
...state,
|
||||
searchResults: undefined,
|
||||
selectedCollectionSummaryID: undefined,
|
||||
extraVisiblePerson: undefined,
|
||||
searchResults: undefined,
|
||||
view: {
|
||||
type: "hidden-albums",
|
||||
activeCollectionSummaryID: HIDDEN_ITEMS_SECTION,
|
||||
activeCollection: undefined,
|
||||
},
|
||||
isInSearchMode: false,
|
||||
};
|
||||
});
|
||||
case "showAlbums": {
|
||||
const { view, selectedCollectionSummaryID } =
|
||||
deriveAlbumsViewAndSelectedID(
|
||||
@@ -617,19 +648,21 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
state.collectionSummaries,
|
||||
state.selectedCollectionSummaryID,
|
||||
);
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbums({
|
||||
...state,
|
||||
searchResults: undefined,
|
||||
selectedCollectionSummaryID,
|
||||
extraVisiblePerson: undefined,
|
||||
searchResults: undefined,
|
||||
view,
|
||||
isInSearchMode: false,
|
||||
};
|
||||
});
|
||||
}
|
||||
case "showNormalOrHiddenCollectionSummary":
|
||||
return {
|
||||
return refreshingFilteredFilesIfShowingAlbumsOrHiddenAlbums({
|
||||
...state,
|
||||
searchResults: undefined,
|
||||
selectedCollectionSummaryID: action.collectionSummaryID,
|
||||
extraVisiblePerson: undefined,
|
||||
searchResults: undefined,
|
||||
view: {
|
||||
type:
|
||||
action.collectionSummaryID !== undefined &&
|
||||
@@ -645,43 +678,58 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
.find(({ id }) => id === action.collectionSummaryID),
|
||||
},
|
||||
isInSearchMode: false,
|
||||
};
|
||||
});
|
||||
case "showPeople": {
|
||||
const view = derivePeopleView(
|
||||
const { view, extraVisiblePerson } = derivePeopleView(
|
||||
state.peopleState,
|
||||
state.tempDeletedFileIDs,
|
||||
state.tempHiddenFileIDs,
|
||||
state.selectedPersonID,
|
||||
state.extraVisiblePerson,
|
||||
);
|
||||
const filteredFiles = derivePeopleFilteredFiles(state.files, view);
|
||||
return {
|
||||
...state,
|
||||
searchResults: undefined,
|
||||
selectedPersonID: view.activePerson?.id,
|
||||
extraVisiblePerson,
|
||||
searchResults: undefined,
|
||||
view,
|
||||
isInSearchMode: false,
|
||||
filteredFiles,
|
||||
};
|
||||
}
|
||||
case "showPerson": {
|
||||
const view = derivePeopleView(
|
||||
const { view, extraVisiblePerson } = derivePeopleView(
|
||||
state.peopleState,
|
||||
state.tempDeletedFileIDs,
|
||||
state.tempHiddenFileIDs,
|
||||
action.personID,
|
||||
state.extraVisiblePerson,
|
||||
);
|
||||
const filteredFiles = derivePeopleFilteredFiles(state.files, view);
|
||||
return {
|
||||
...state,
|
||||
searchResults: undefined,
|
||||
selectedPersonID: view.activePerson?.id,
|
||||
extraVisiblePerson,
|
||||
view,
|
||||
isInSearchMode: false,
|
||||
filteredFiles,
|
||||
};
|
||||
}
|
||||
case "enterSearchMode":
|
||||
return { ...state, isInSearchMode: true };
|
||||
case "searchResults":
|
||||
case "setSearchResults":
|
||||
return {
|
||||
...state,
|
||||
searchResults: action.searchResults,
|
||||
filteredFiles: state.isInSearchMode
|
||||
? action.searchResults
|
||||
: state.filteredFiles,
|
||||
};
|
||||
case "enterSearchMode":
|
||||
return {
|
||||
...state,
|
||||
isInSearchMode: true,
|
||||
filteredFiles: state.searchResults ?? state.filteredFiles,
|
||||
};
|
||||
case "exitSearch":
|
||||
return {
|
||||
@@ -689,8 +737,6 @@ const galleryReducer: React.Reducer<GalleryState, GalleryAction> = (
|
||||
isInSearchMode: false,
|
||||
searchResults: undefined,
|
||||
};
|
||||
case "setFilteredFiles":
|
||||
return { ...state, filteredFiles: action.filteredFiles };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -721,7 +767,7 @@ export const uniqueFilesByID = (files: EnteFile[]) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to compute archived collection IDs from their dependencies.
|
||||
* Compute archived collection IDs from their dependencies.
|
||||
*/
|
||||
const deriveArchivedCollectionIDs = (collections: Collection[]) =>
|
||||
new Set<number>(
|
||||
@@ -731,20 +777,19 @@ const deriveArchivedCollectionIDs = (collections: Collection[]) =>
|
||||
);
|
||||
|
||||
/**
|
||||
* Helper function to compute the default hidden collection IDs from theirq
|
||||
* dependencies.
|
||||
* Compute the default hidden collection IDs from their dependencies.
|
||||
*/
|
||||
const deriveDefaultHiddenCollectionIDs = (hiddenCollections: Collection[]) =>
|
||||
findDefaultHiddenCollectionIDs(hiddenCollections);
|
||||
|
||||
/**
|
||||
* Helper function to compute hidden file IDs from their dependencies.
|
||||
* Compute hidden file IDs from their dependencies.
|
||||
*/
|
||||
const deriveHiddenFileIDs = (hiddenFiles: EnteFile[]) =>
|
||||
new Set<number>(hiddenFiles.map((f) => f.id));
|
||||
|
||||
/**
|
||||
* Helper function to compute favorite file IDs from their dependencies.
|
||||
* Compute favorite file IDs from their dependencies.
|
||||
*/
|
||||
const deriveFavoriteFileIDs = (
|
||||
collections: Collection[],
|
||||
@@ -763,9 +808,9 @@ const deriveFavoriteFileIDs = (
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to compute collection summaries from their dependencies.
|
||||
* Compute collection summaries from their dependencies.
|
||||
*/
|
||||
export const deriveCollectionSummaries = (
|
||||
const deriveCollectionSummaries = (
|
||||
user: User,
|
||||
collections: Collection[],
|
||||
files: EnteFile[],
|
||||
@@ -817,10 +862,9 @@ const pseudoCollectionOptionsForFiles = (files: EnteFile[]) => ({
|
||||
});
|
||||
|
||||
/**
|
||||
* Helper function to compute hidden collection summaries from their
|
||||
* dependencies.
|
||||
* Compute hidden collection summaries from their dependencies.
|
||||
*/
|
||||
export const deriveHiddenCollectionSummaries = (
|
||||
const deriveHiddenCollectionSummaries = (
|
||||
user: User,
|
||||
hiddenCollections: Collection[],
|
||||
hiddenFiles: EnteFile[],
|
||||
@@ -997,8 +1041,8 @@ const findAllSectionVisibleFiles = (
|
||||
);
|
||||
|
||||
/**
|
||||
* Helper function to derive the {@link GalleryView} from its dependencies when
|
||||
* we are switching to (or back to) the "albums" view.
|
||||
* Compute the {@link GalleryView} from its dependencies when we are switching
|
||||
* to (or back to) the "albums" view.
|
||||
*/
|
||||
const deriveAlbumsViewAndSelectedID = (
|
||||
collections: GalleryState["collections"],
|
||||
@@ -1023,15 +1067,19 @@ const deriveAlbumsViewAndSelectedID = (
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to derive the {@link GalleryView} from its dependencies when
|
||||
* we are switching to (or back to) the "people" view.
|
||||
* Compute the {@link GalleryView} from its dependencies when we are switching
|
||||
* to (or back to) the "people" view.
|
||||
*/
|
||||
const derivePeopleView = (
|
||||
peopleState: GalleryState["peopleState"],
|
||||
tempDeletedFileIDs: GalleryState["tempDeletedFileIDs"],
|
||||
tempHiddenFileIDs: GalleryState["tempHiddenFileIDs"],
|
||||
selectedPersonID: GalleryState["selectedPersonID"],
|
||||
): Extract<GalleryView, { type: "people" }> => {
|
||||
extraVisiblePerson: GalleryState["extraVisiblePerson"],
|
||||
): {
|
||||
view: Extract<GalleryView, { type: "people" }>;
|
||||
extraVisiblePerson: GalleryState["extraVisiblePerson"];
|
||||
} => {
|
||||
let people = peopleState?.people ?? [];
|
||||
let visiblePeople = peopleState?.visiblePeople ?? [];
|
||||
if (tempDeletedFileIDs.size + tempHiddenFileIDs.size > 0) {
|
||||
@@ -1052,58 +1100,85 @@ const derivePeopleView = (
|
||||
people = filterTemp(people);
|
||||
visiblePeople = filterTemp(visiblePeople);
|
||||
}
|
||||
const findByID = (ps: Person[]) => ps.find((p) => p.id == selectedPersonID);
|
||||
let activePerson = findByID(visiblePeople);
|
||||
|
||||
const findByIDIn = (ps: Person[]) =>
|
||||
ps.find((p) => p.id == selectedPersonID);
|
||||
let activePerson = findByIDIn(visiblePeople);
|
||||
if (!activePerson) {
|
||||
// This might be one of the normally hidden small clusters.
|
||||
activePerson = findByID(people);
|
||||
activePerson = findByIDIn(people);
|
||||
if (activePerson) {
|
||||
// Temporarily add this person's entry to the list of people
|
||||
// surfaced in the people section.
|
||||
visiblePeople.push(activePerson);
|
||||
// surfaced in the people view.
|
||||
extraVisiblePerson = activePerson;
|
||||
} else {
|
||||
// We don't have an "All" pseudo-album in people mode, so default to
|
||||
// We don't have an "All" pseudo-album in people view, so default to
|
||||
// the first person in the list (if any).
|
||||
activePerson = visiblePeople[0];
|
||||
}
|
||||
}
|
||||
|
||||
return { type: "people", visiblePeople, activePerson };
|
||||
const view = {
|
||||
type: "people" as const,
|
||||
visiblePeople: extraVisiblePerson
|
||||
? visiblePeople.concat([extraVisiblePerson])
|
||||
: visiblePeople,
|
||||
activePerson,
|
||||
};
|
||||
|
||||
return { view, extraVisiblePerson };
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to compute the sorted list of files to show when we're
|
||||
* showing either "albums" or "hidden-albums".
|
||||
* Return a new state by recomputing the {@link filteredFiles} property if we're
|
||||
* showing the "albums" view.
|
||||
*
|
||||
* Usually, we update state by manually dependency tracking on a fine grained
|
||||
* basis, but it is cumbersome (and mistake prone) to do that for the list of
|
||||
* filtered files which depend on a many things. So this is a convenience
|
||||
* function for recomputing filtered files whenever any bit of the underlying
|
||||
* state that could affect the "albums" view changes (and we're showing it).
|
||||
*/
|
||||
export const deriveAlbumishFilteredFiles = (state: GalleryState) => {
|
||||
const view = state.view;
|
||||
if (view?.type == "albums") {
|
||||
return deriveAlbumsFilteredFiles(state, view);
|
||||
} else if (view?.type == "hidden-albums") {
|
||||
return deriveHiddenAlbumsFilteredFiles(state, view);
|
||||
const refreshingFilteredFilesIfShowingAlbums = (state: GalleryState) => {
|
||||
if (state.view?.type == "albums") {
|
||||
const filteredFiles = deriveAlbumsFilteredFiles(
|
||||
state.files,
|
||||
state.trashedFiles,
|
||||
state.archivedCollectionIDs,
|
||||
state.hiddenFileIDs,
|
||||
state.tempDeletedFileIDs,
|
||||
state.tempHiddenFileIDs,
|
||||
state.view,
|
||||
);
|
||||
return { ...state, filteredFiles };
|
||||
} else {
|
||||
// TODO: Setup the types so that we don't come here.
|
||||
throw new Error("Not implemented");
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to compute the sorted list of files to show when we're
|
||||
* in the "albums" view.
|
||||
* Compute the sorted list of files to show when we're in the "albums" view and
|
||||
* the dependencies change.
|
||||
*/
|
||||
export const deriveAlbumsFilteredFiles = (
|
||||
state: GalleryState,
|
||||
const deriveAlbumsFilteredFiles = (
|
||||
files: GalleryState["files"],
|
||||
trashedFiles: GalleryState["trashedFiles"],
|
||||
archivedCollectionIDs: GalleryState["archivedCollectionIDs"],
|
||||
hiddenFileIDs: GalleryState["hiddenFileIDs"],
|
||||
tempDeletedFileIDs: GalleryState["tempDeletedFileIDs"],
|
||||
tempHiddenFileIDs: GalleryState["tempHiddenFileIDs"],
|
||||
view: Extract<GalleryView, { type: "albums" | "hidden-albums" }>,
|
||||
) => {
|
||||
const {
|
||||
files,
|
||||
archivedCollectionIDs,
|
||||
hiddenFileIDs,
|
||||
tempDeletedFileIDs,
|
||||
tempHiddenFileIDs,
|
||||
} = state;
|
||||
const activeCollectionSummaryID = view.activeCollectionSummaryID;
|
||||
|
||||
// Trash is dealt with separately.
|
||||
if (activeCollectionSummaryID === TRASH_SECTION) {
|
||||
return uniqueFilesByID([
|
||||
...trashedFiles,
|
||||
...files.filter((file) => tempDeletedFileIDs.has(file.id)),
|
||||
]);
|
||||
}
|
||||
|
||||
const filteredFiles = files.filter((file) => {
|
||||
if (tempDeletedFileIDs.has(file.id)) return false;
|
||||
if (hiddenFileIDs.has(file.id)) return false;
|
||||
@@ -1137,31 +1212,48 @@ export const deriveAlbumsFilteredFiles = (
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to compute the sorted list of files to show when we're
|
||||
* showing the "Trash".
|
||||
* Return a new state by recomputing the {@link filteredFiles} property if when
|
||||
* we're showing the "hidden-albums" view.
|
||||
*
|
||||
* See {@link refreshingFilteredFilesIfShowingAlbums} for more details.
|
||||
*/
|
||||
export const deriveTrashFilteredFiles = ({
|
||||
files,
|
||||
trashedFiles,
|
||||
tempDeletedFileIDs,
|
||||
}: GalleryState) =>
|
||||
uniqueFilesByID([
|
||||
...trashedFiles,
|
||||
...files.filter((file) => tempDeletedFileIDs.has(file.id)),
|
||||
]);
|
||||
const refreshingFilteredFilesIfShowingHiddenAlbums = (state: GalleryState) => {
|
||||
if (state.view?.type == "hidden-albums") {
|
||||
const filteredFiles = deriveHiddenAlbumsFilteredFiles(
|
||||
state.hiddenFiles,
|
||||
state.defaultHiddenCollectionIDs,
|
||||
state.tempDeletedFileIDs,
|
||||
state.view,
|
||||
);
|
||||
return { ...state, filteredFiles };
|
||||
} else {
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to compute the sorted list of files to show when we're
|
||||
* in the "hidden-albums" view.
|
||||
* Convenience method for chaining the refresh functions for "albums" and
|
||||
* "hidden-albums". This is useful if something that potentially affects both
|
||||
* scenarios changes.
|
||||
*/
|
||||
export const deriveHiddenAlbumsFilteredFiles = (
|
||||
const refreshingFilteredFilesIfShowingAlbumsOrHiddenAlbums = (
|
||||
state: GalleryState,
|
||||
) =>
|
||||
refreshingFilteredFilesIfShowingHiddenAlbums(
|
||||
refreshingFilteredFilesIfShowingAlbums(state),
|
||||
);
|
||||
|
||||
/**
|
||||
* Compute the sorted list of files to show when we're in the "hidden-albums"
|
||||
* view and the dependencies change.
|
||||
*/
|
||||
const deriveHiddenAlbumsFilteredFiles = (
|
||||
hiddenFiles: GalleryState["hiddenFiles"],
|
||||
defaultHiddenCollectionIDs: GalleryState["defaultHiddenCollectionIDs"],
|
||||
tempDeletedFileIDs: GalleryState["tempDeletedFileIDs"],
|
||||
view: Extract<GalleryView, { type: "albums" | "hidden-albums" }>,
|
||||
) => {
|
||||
const { hiddenFiles, defaultHiddenCollectionIDs, tempDeletedFileIDs } =
|
||||
state;
|
||||
const activeCollectionSummaryID = view.activeCollectionSummaryID;
|
||||
|
||||
const filteredFiles = hiddenFiles.filter((file) => {
|
||||
if (tempDeletedFileIDs.has(file.id)) return false;
|
||||
|
||||
@@ -1199,11 +1291,11 @@ const sortAndUniqueFilteredFiles = (
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to compute the sorted list of files to show when we're
|
||||
* in the "people" view.
|
||||
* Compute the sorted list of files to show when we're in the "people" view and
|
||||
* the dependencies change.
|
||||
*/
|
||||
export const derivePeopleFilteredFiles = (
|
||||
{ files }: GalleryState,
|
||||
const derivePeopleFilteredFiles = (
|
||||
files: GalleryState["files"],
|
||||
view: Extract<GalleryView, { type: "people" }>,
|
||||
) => {
|
||||
const pfSet = new Set(view.activePerson?.fileIDs ?? []);
|
||||
|
||||
Reference in New Issue
Block a user