Reset cache
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
CollectionSelector,
|
||||
type CollectionSelectorAttributes,
|
||||
} from "@/new/photos/components/CollectionSelector";
|
||||
import { resetFileViewerDataSourceOnClose } from "@/new/photos/components/FileViewerComponents-temp";
|
||||
import { PlanSelector } from "@/new/photos/components/PlanSelector";
|
||||
import {
|
||||
SearchBar,
|
||||
@@ -564,11 +565,14 @@ const Page: React.FC = () => {
|
||||
(hiddenFiles) =>
|
||||
dispatch({ type: "fetchHiddenFiles", hiddenFiles }),
|
||||
);
|
||||
if (didUpdateNormalFiles || didUpdateHiddenFiles)
|
||||
exportService.onLocalFilesUpdated();
|
||||
await syncTrash(allCollections, (trashedFiles: EnteFile[]) =>
|
||||
dispatch({ type: "setTrashedFiles", trashedFiles }),
|
||||
);
|
||||
if (didUpdateNormalFiles || didUpdateHiddenFiles) {
|
||||
exportService.onLocalFilesUpdated();
|
||||
// TODO(PS): Use direct one
|
||||
resetFileViewerDataSourceOnClose();
|
||||
}
|
||||
// syncWithRemote is called with the force flag set to true before
|
||||
// doing an upload. So it is possible, say when resuming a pending
|
||||
// upload, that we get two syncWithRemotes happening in parallel.
|
||||
|
||||
@@ -213,7 +213,6 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
setNeedsSync((needSync) => {
|
||||
console.log("needs sync", needSync);
|
||||
if (needSync) onTriggerSyncWithRemote?.();
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -38,6 +38,15 @@ interface PhotoSwipeSlideData {
|
||||
* The height (in pixels) of the {@link src} image.
|
||||
*/
|
||||
height?: number | undefined;
|
||||
/**
|
||||
* The alt text associated with the file.
|
||||
*
|
||||
* This will be set to the file's caption. PhotoSwipe will use it as the alt
|
||||
* text when constructing img elements (if any) for this item. We will also
|
||||
* use this for displaying the visible "caption" element atop the file (both
|
||||
* images and video).
|
||||
*/
|
||||
alt?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,15 +107,6 @@ export type ItemData = PhotoSwipeSlideData & {
|
||||
* It is set while the thumbnail is loaded.
|
||||
*/
|
||||
isContentZoomable?: boolean;
|
||||
/**
|
||||
* The alt text associated with the file.
|
||||
*
|
||||
* This will be set to the file's caption. PhotoSwipe will use it as the alt
|
||||
* text when constructing img elements (if any) for this item. We will also
|
||||
* use this for displaying the visible "caption" element atop the file (both
|
||||
* images and video).
|
||||
*/
|
||||
alt?: string;
|
||||
/**
|
||||
* This will be `true` if the fetch for the file's data has failed.
|
||||
*
|
||||
@@ -127,6 +127,19 @@ export type ItemData = PhotoSwipeSlideData & {
|
||||
* This will be cleared on logout.
|
||||
*/
|
||||
class FileViewerDataSourceState {
|
||||
/**
|
||||
* Non-zero if a file viewer is currently open.
|
||||
*
|
||||
* This is a counter, but the file viewer data source has other many
|
||||
* assumptions about only a single instance of PhotoSwipe being active at a
|
||||
* time, so this could've been a boolean as well.
|
||||
*/
|
||||
viewerCount = 0;
|
||||
/**
|
||||
* True if our state needs to be cleared the next time the file viewer is
|
||||
* closed.
|
||||
*/
|
||||
needsReset = false;
|
||||
/**
|
||||
* The best data we have for a particular file (ID).
|
||||
*/
|
||||
@@ -154,12 +167,59 @@ class FileViewerDataSourceState {
|
||||
*/
|
||||
let _state = new FileViewerDataSourceState();
|
||||
|
||||
const resetState = () => {
|
||||
_state = new FileViewerDataSourceState();
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear any internal state maintained by the file viewer data source.
|
||||
*/
|
||||
// TODO(PS): Call me during logout sequence once this is integrated.
|
||||
export const logoutFileViewerDataSource = () => {
|
||||
_state = new FileViewerDataSourceState();
|
||||
export const logoutFileViewerDataSource = resetState;
|
||||
|
||||
/**
|
||||
* Clear any internal state if possible. This is invoked when files have been
|
||||
* updated on remote, and those changes synced locally.
|
||||
*
|
||||
* Because we also retain callbacks, clearing existing item data when the file
|
||||
* viewer is open can lead to problematic edge cases. Thus, this function
|
||||
* behaves in two different ways:
|
||||
*
|
||||
* - If the file viewer is already open, then we enqueue a reset for when it is
|
||||
* closed the next time.
|
||||
*
|
||||
* - Otherwise we immediately reset our state.
|
||||
*
|
||||
* See: [Note: Changes to underlying files when file viewer is open]
|
||||
*/
|
||||
export const resetFileViewerDataSourceOnClose = () => {
|
||||
if (_state.viewerCount) {
|
||||
_state.needsReset = true;
|
||||
} else {
|
||||
resetState();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by the file viewer whenever it is opened.
|
||||
*/
|
||||
export const fileViewerWillOpen = () => {
|
||||
_state.viewerCount++;
|
||||
};
|
||||
|
||||
/**
|
||||
* Called by the file viewer whenever it has been closed.
|
||||
*/
|
||||
export const fileViewerDidClose = () => {
|
||||
_state.viewerCount--;
|
||||
if (_state.needsReset && _state.viewerCount == 0) {
|
||||
// Reset everything.
|
||||
resetState();
|
||||
} else {
|
||||
// Selectively clear.
|
||||
forgetFailedItems();
|
||||
forgetExif();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -246,7 +306,7 @@ export const forgetFailedItemDataForFileID = (fileID: number) => {
|
||||
* This is called when the user closes the file viewer so that we attempt a full
|
||||
* retry when they reopen the viewer the next time.
|
||||
*/
|
||||
export const forgetFailedItems = () =>
|
||||
const forgetFailedItems = () =>
|
||||
[..._state.itemDataByFileID.keys()].forEach(forgetFailedItemDataForFileID);
|
||||
|
||||
const enqueueUpdates = async (file: EnteFile) => {
|
||||
@@ -258,7 +318,12 @@ const enqueueUpdates = async (file: EnteFile) => {
|
||||
// the visible caption).
|
||||
const alt = fileCaption(file);
|
||||
|
||||
_state.itemDataByFileID.set(file.id, { ...itemData, fileType, fileID, alt });
|
||||
_state.itemDataByFileID.set(file.id, {
|
||||
...itemData,
|
||||
fileType,
|
||||
fileID,
|
||||
alt,
|
||||
});
|
||||
_state.needsRefreshByFileID.get(file.id)?.();
|
||||
};
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ import type { EnteFile } from "@/media/file";
|
||||
import { FileType } from "@/media/file-type";
|
||||
import { t } from "i18next";
|
||||
import {
|
||||
forgetExif,
|
||||
fileViewerDidClose,
|
||||
fileViewerWillOpen,
|
||||
forgetExifForItemData,
|
||||
forgetFailedItemDataForFileID,
|
||||
forgetFailedItems,
|
||||
itemDataForFile,
|
||||
updateFileInfoExifIfNeeded,
|
||||
} from "./data-source";
|
||||
@@ -58,10 +58,6 @@ export interface FileViewerFileAnnotation {
|
||||
* and the edit action should therefore be shown for this file.
|
||||
*/
|
||||
isEditableImage: boolean;
|
||||
/**
|
||||
* The caption ("description") of the file (if any).
|
||||
*/
|
||||
caption: string | undefined;
|
||||
}
|
||||
|
||||
export interface FileViewerPhotoSwipeDelegate {
|
||||
@@ -464,8 +460,7 @@ export class FileViewerPhotoSwipe {
|
||||
// completed.
|
||||
pswp.on("destroy", () => {
|
||||
this.clearAutoHideIntervalIfNeeded();
|
||||
forgetFailedItems();
|
||||
forgetExif();
|
||||
fileViewerDidClose();
|
||||
// Let our parent know that we have been closed.
|
||||
onClose();
|
||||
});
|
||||
@@ -654,6 +649,9 @@ export class FileViewerPhotoSwipe {
|
||||
return element;
|
||||
});
|
||||
|
||||
// Let our data source know.
|
||||
fileViewerWillOpen();
|
||||
|
||||
// Initializing PhotoSwipe adds it to the DOM as a dialog-like div with
|
||||
// the class "pswp".
|
||||
pswp.init();
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// TODO(PS): Temporary trampoline
|
||||
export const resetFileViewerDataSourceOnClose = async () => {
|
||||
if (!process.env.NEXT_PUBLIC_ENTE_WIP_PS5) return;
|
||||
(
|
||||
await import("@/gallery/components/viewer/data-source")
|
||||
).resetFileViewerDataSourceOnClose();
|
||||
};
|
||||
@@ -16,6 +16,7 @@ import dynamic from "next/dynamic";
|
||||
const FV5 = dynamic(() => import("@/gallery/components/viewer/FileViewer"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const FVD = () => <></>;
|
||||
|
||||
export const FileViewer: React.FC = (props) => {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { isMLSupported, mlStatusSync, mlSync } from "@/new/photos/services/ml";
|
||||
import { searchDataSync } from "@/new/photos/services/search";
|
||||
import { syncSettings } from "@/new/photos/services/settings";
|
||||
import { splitByPredicate } from "@/utils/array";
|
||||
import { resetFileViewerDataSourceOnClose } from "../components/FileViewerComponents-temp";
|
||||
|
||||
/**
|
||||
* Part 1 of {@link sync}. See TODO below for why this is split.
|
||||
@@ -62,17 +63,23 @@ export const syncFilesAndCollections = async () => {
|
||||
allCollections,
|
||||
isHiddenCollection,
|
||||
);
|
||||
await syncFiles(
|
||||
const didUpdateNormalFiles = await syncFiles(
|
||||
"normal",
|
||||
normalCollections,
|
||||
() => {},
|
||||
() => {},
|
||||
);
|
||||
await syncFiles(
|
||||
const didUpdateHiddenFiles = await syncFiles(
|
||||
"hidden",
|
||||
hiddenCollections,
|
||||
() => {},
|
||||
() => {},
|
||||
);
|
||||
await syncTrash(allCollections, () => {});
|
||||
if (didUpdateNormalFiles || didUpdateHiddenFiles) {
|
||||
// TODO:
|
||||
// exportService.onLocalFilesUpdated();
|
||||
// TODO(PS): Use direct one
|
||||
await resetFileViewerDataSourceOnClose();
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user