Pick the latest from files

This commit is contained in:
Manav Rathi
2025-03-13 10:01:50 +05:30
parent 1f8fa69f8b
commit efb6656c28
2 changed files with 62 additions and 39 deletions

View File

@@ -15,7 +15,10 @@ import { FullScreenDropZone } from "@/gallery/components/FullScreenDropZone";
import { resetFileViewerDataSourceOnClose } from "@/gallery/components/viewer/data-source"; import { resetFileViewerDataSourceOnClose } from "@/gallery/components/viewer/data-source";
import { type Collection } from "@/media/collection"; import { type Collection } from "@/media/collection";
import { mergeMetadata, type EnteFile } from "@/media/file"; import { mergeMetadata, type EnteFile } from "@/media/file";
import type { ItemVisibility } from "@/media/file-metadata"; import {
updateRemotePrivateMagicMetadata,
type ItemVisibility,
} from "@/media/file-metadata";
import { import {
CollectionSelector, CollectionSelector,
type CollectionSelectorAttributes, type CollectionSelectorAttributes,
@@ -132,12 +135,7 @@ import {
getSelectedCollection, getSelectedCollection,
handleCollectionOps, handleCollectionOps,
} from "utils/collection"; } from "utils/collection";
import { import { FILE_OPS_TYPE, getSelectedFiles, handleFileOps } from "utils/file";
FILE_OPS_TYPE,
changeFilesVisibility,
getSelectedFiles,
handleFileOps,
} from "utils/file";
const defaultGalleryContext: GalleryContextType = { const defaultGalleryContext: GalleryContextType = {
setActiveCollectionID: () => null, setActiveCollectionID: () => null,
@@ -817,7 +815,8 @@ const Page: React.FC = () => {
}; };
const handleFileViewerFileVisibilityUpdate = useCallback( const handleFileViewerFileVisibilityUpdate = useCallback(
async (fileID: number, visibility: ItemVisibility) => { async (file: EnteFile, visibility: ItemVisibility) => {
const fileID = file.id;
dispatch({ dispatch({
type: "markPendingVisibilityUpdate", type: "markPendingVisibilityUpdate",
fileID, fileID,
@@ -825,7 +824,10 @@ const Page: React.FC = () => {
}); });
try { try {
await changeFilesVisibility(files, visibility); updateRemotePrivateMagicMetadata(file, { visibility });
// TODO(AR): Need to trigger a "lite" sync (or update that
// particular file in the reducer state in some other way).
// See: [Note: File viewer update and dispatch] // See: [Note: File viewer update and dispatch]
dispatch({ dispatch({
type: "markUnsyncedVisibilityUpdate", type: "markUnsyncedVisibilityUpdate",

View File

@@ -144,10 +144,10 @@ export interface FileViewerToggleArchiveButtonProps {
*/ */
unsyncedVisibilityUpdates?: Map<number, ItemVisibility>; unsyncedVisibilityUpdates?: Map<number, ItemVisibility>;
/** /**
* Update the {@link visibility} of the file with the given {@link fileID}. * Update the {@link visibility} of the given {@link file}.
*/ */
onFileVisibilityUpdate?: ( onFileVisibilityUpdate?: (
fileID: number, file: EnteFile,
visibility: ItemVisibility, visibility: ItemVisibility,
) => Promise<void>; ) => Promise<void>;
} }
@@ -464,36 +464,57 @@ export const FileViewer: React.FC<FileViewerProps> = ({
// `onFileVisibilityUpdate` will asynchronously result in updates to // `onFileVisibilityUpdate` will asynchronously result in updates to
// the `files` prop. // the `files` prop.
// //
// Currently that indeed is what happens as the last call in the // Currently that is indeed what happens because the last call in
// `onDelete` and `onFileVisibilityUpdate` implementations are calls // the `onDelete` and `onFileVisibilityUpdate` implementations are
// to a (useReducer) dispatcher, but we need to be careful about // calls to a (useReducer) dispatcher, but we need to be careful
// preserving this assumption if changing their implementation in // about preserving this assumption when changing their
// the future. // implementation in the future.
awaitNextFilesOrFavoritesUpdate((files: EnteFile[]) => { awaitNextFilesOrFavoritesUpdate((files: EnteFile[]) => {
handleNeedsRemoteSync(); handleNeedsRemoteSync();
// We might've been provided an expectedFileID. If so, only do
// the reload if it is no longer present in the files array.
//
// There are 3 cases:
//
// 1. On file deletion: expectedFileID is not provided.
//
// 2. On file archive when we're in the all section:
// expectedFileID is provided, and will not be present in the
// updated files array after update. In such cases, we want
// to behave like delete (move to the next slide).
//
// 3. On other types of file archive: expectedFileID is
// provided, but it'll still be present in the updated files
// array, and in such cases we don't want to reload the
// current slide. Instead, we only modify the file attribute
// of the currentAnnotatedFile (if appropriate).
if (files.length) { if (files.length) {
// We might've been provided an expectedFileID. If so, only const updatedFile = expectedFileID
// do the reload if it is no longer present in the files ? files.find(({ id }) => id == expectedFileID)
// array. : undefined;
// if (updatedFile) {
// There are 3 cases: setActiveAnnotatedFile((activeAnnotatedFile) => {
// // Modify the file attribute of activeAnnotatedFile
// - On file deletion: expectedFileID is not provided. // if we're still showing a slide with a file that
// // has the same ID as the one we expected to modify.
// - On file archive when we're in the all section: //
// expectedFileID is provided, and will not be present in // In the case of delete, this code will not run,
// the updated files array after update. In such cases, we // and in the case of toggling archive, none of the
// want to behave like delete (move to the next slide). // other attributes of activeAnnotatedFile currently
// // depend on the archive status change, so this is
// - On other types of file archive: expectedFileID is // safe. But it is still on the kludgy side, and
// provided, but it'll still be present in the updated // might need care with future changes.
// files array, and in such cases we don't want to reload //
// the current slide. // (We don't do a full refresh since that would
if ( // cause the user to lose their pan / zoom etc)
expectedFileID && if (
files.find(({ id }) => id == expectedFileID) activeAnnotatedFile &&
) { activeAnnotatedFile.file.id == expectedFileID
// Do nothing. ) {
activeAnnotatedFile.file = updatedFile;
}
return activeAnnotatedFile;
});
} else { } else {
// Refreshing the current slide after the current file // Refreshing the current slide after the current file
// has gone will show the subsequent slide (since that // has gone will show the subsequent slide (since that
@@ -771,7 +792,7 @@ export const FileViewer: React.FC<FileViewerProps> = ({
toggleArchived = () => { toggleArchived = () => {
handleMoreMenuCloseIfNeeded(); handleMoreMenuCloseIfNeeded();
void onFileVisibilityUpdate( void onFileVisibilityUpdate(
file.id, file,
isArchived isArchived
? ItemVisibility.visible ? ItemVisibility.visible
: ItemVisibility.archived, : ItemVisibility.archived,