mirror of
https://github.com/ente-io/ente.git
synced 2025-08-13 17:57:31 +00:00
delegate
This commit is contained in:
@@ -396,7 +396,7 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
//
|
||||
// Not memoized since it uses the frequently changing `activeAnnotatedFile`.
|
||||
const handleDownloadMenuAction = () => {
|
||||
handleMoreMenuClose();
|
||||
handleMoreMenuCloseIfNeeded();
|
||||
onDownload!(activeAnnotatedFile!.file);
|
||||
};
|
||||
|
||||
@@ -413,9 +413,9 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
[],
|
||||
);
|
||||
|
||||
const handleMoreMenuClose = useCallback(() => {
|
||||
const handleMoreMenuCloseIfNeeded = useCallback(() => {
|
||||
setMoreMenuAnchorEl((el) => {
|
||||
resetMoreMenuButtonOnMenuClose(el);
|
||||
if (el) resetMoreMenuButtonOnMenuClose(el);
|
||||
return null;
|
||||
});
|
||||
}, []);
|
||||
@@ -423,11 +423,11 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
const handleConfirmDelete = useMemo(() => {
|
||||
return onDelete
|
||||
? () => {
|
||||
handleMoreMenuClose();
|
||||
handleMoreMenuCloseIfNeeded();
|
||||
showConfirmDelete();
|
||||
}
|
||||
: undefined;
|
||||
}, [onDelete, showConfirmDelete, handleMoreMenuClose]);
|
||||
}, [onDelete, showConfirmDelete, handleMoreMenuCloseIfNeeded]);
|
||||
|
||||
// Not memoized since it uses the frequently changing `activeAnnotatedFile`.
|
||||
const handleDelete = async () => {
|
||||
@@ -455,8 +455,8 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
};
|
||||
|
||||
// Not memoized since it uses the frequently changing `activeAnnotatedFile`.
|
||||
const handleCopyImage = () => {
|
||||
handleMoreMenuClose();
|
||||
const handleCopyImage = useCallback(() => {
|
||||
handleMoreMenuCloseIfNeeded();
|
||||
// Safari does not copy if we do not call `navigator.clipboard.write`
|
||||
// synchronously within the click event handler, but it does supports
|
||||
// passing a promise in lieu of the blob.
|
||||
@@ -467,16 +467,16 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
}),
|
||||
])
|
||||
.catch(onGenericError);
|
||||
};
|
||||
}, [onGenericError, handleMoreMenuCloseIfNeeded, activeImageURL]);
|
||||
|
||||
const handleEditImage = useMemo(() => {
|
||||
return onSaveEditedImageCopy
|
||||
? () => {
|
||||
handleMoreMenuClose();
|
||||
handleMoreMenuCloseIfNeeded();
|
||||
setOpenImageEditor(true);
|
||||
}
|
||||
: undefined;
|
||||
}, [onSaveEditedImageCopy, handleMoreMenuClose]);
|
||||
}, [onSaveEditedImageCopy, handleMoreMenuCloseIfNeeded]);
|
||||
|
||||
const handleImageEditorClose = useCallback(
|
||||
() => setOpenImageEditor(false),
|
||||
@@ -616,22 +616,49 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
}, []);
|
||||
|
||||
const handleToggleFullscreen = useCallback(() => {
|
||||
handleMoreMenuClose();
|
||||
handleMoreMenuCloseIfNeeded();
|
||||
void (
|
||||
document.fullscreenElement
|
||||
? document.exitFullscreen()
|
||||
: document.body.requestFullscreen()
|
||||
).then(updateFullscreenStatus);
|
||||
}, [handleMoreMenuClose, updateFullscreenStatus]);
|
||||
}, [handleMoreMenuCloseIfNeeded, updateFullscreenStatus]);
|
||||
|
||||
const handleShortcuts = useCallback(() => {
|
||||
handleMoreMenuClose();
|
||||
handleMoreMenuCloseIfNeeded();
|
||||
showShortcuts();
|
||||
}, [handleMoreMenuClose, showShortcuts]);
|
||||
}, [handleMoreMenuCloseIfNeeded, showShortcuts]);
|
||||
|
||||
const performKeyAction = useCallback(
|
||||
(action): FileViewerPhotoSwipeDelegate["performKeyAction"] => {
|
||||
switch (action) {
|
||||
case "delete":
|
||||
handleConfirmDelete?.();
|
||||
break;
|
||||
case "copy":
|
||||
if (activeImageURL) handleCopyImage();
|
||||
break;
|
||||
case "toggle-fullscreen":
|
||||
handleToggleFullscreen();
|
||||
break;
|
||||
}
|
||||
},
|
||||
[
|
||||
handleConfirmDelete,
|
||||
activeImageURL,
|
||||
handleCopyImage,
|
||||
handleToggleFullscreen,
|
||||
],
|
||||
);
|
||||
|
||||
// Initial value of delegate.
|
||||
if (!delegateRef.current) {
|
||||
delegateRef.current = { getFiles, isFavorite, toggleFavorite };
|
||||
delegateRef.current = {
|
||||
getFiles,
|
||||
isFavorite,
|
||||
toggleFavorite,
|
||||
performKeyAction,
|
||||
};
|
||||
}
|
||||
|
||||
// Updates to delegate callbacks.
|
||||
@@ -640,7 +667,8 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
delegate.getFiles = getFiles;
|
||||
delegate.isFavorite = isFavorite;
|
||||
delegate.toggleFavorite = toggleFavorite;
|
||||
}, [getFiles, isFavorite, toggleFavorite]);
|
||||
delegate.performKeyAction = performKeyAction;
|
||||
}, [getFiles, isFavorite, toggleFavorite, performKeyAction]);
|
||||
|
||||
// Notify the listeners, if any, for updates to files or favorites.
|
||||
useEffect(() => {
|
||||
@@ -717,7 +745,7 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
/>
|
||||
<MoreMenu
|
||||
open={!!moreMenuAnchorEl}
|
||||
onClose={handleMoreMenuClose}
|
||||
onClose={handleMoreMenuCloseIfNeeded}
|
||||
anchorEl={moreMenuAnchorEl}
|
||||
id={moreMenuID}
|
||||
slotProps={{
|
||||
|
@@ -73,6 +73,15 @@ export interface FileViewerPhotoSwipeDelegate {
|
||||
* > remain in the disabled state (until the file viewer is closed).
|
||||
*/
|
||||
toggleFavorite: (annotatedFile: FileViewerAnnotatedFile) => Promise<void>;
|
||||
/**
|
||||
* Called when the user triggers a potential action using a keyboard
|
||||
* shortcut.
|
||||
*
|
||||
* The caller does not check if the action is valid in the current context,
|
||||
* so the delegate must validate and only then perform the action if it is
|
||||
* appropriate.
|
||||
*/
|
||||
performKeyAction: (action: "delete" | "copy" | "toggle-fullscreen") => void;
|
||||
}
|
||||
|
||||
type FileViewerPhotoSwipeOptions = Pick<
|
||||
@@ -507,8 +516,16 @@ export class FileViewerPhotoSwipe {
|
||||
|
||||
const handleToggleFavorite = () => void toggleFavorite();
|
||||
|
||||
const handleToggleFavoriteIfEnabled = () => {
|
||||
if (haveUser) handleToggleFavorite();
|
||||
};
|
||||
|
||||
const handleDownload = () => onDownload(currentAnnotatedFile());
|
||||
|
||||
const handleDownloadIfEnabled = () => {
|
||||
if (!!currentFileAnnotation().showDownload) handleDownload();
|
||||
};
|
||||
|
||||
const showIf = (element: HTMLElement, condition: boolean) =>
|
||||
condition
|
||||
? element.classList.remove("pswp__hidden")
|
||||
@@ -684,16 +701,27 @@ export class FileViewerPhotoSwipe {
|
||||
return element;
|
||||
});
|
||||
|
||||
// Some actions routed via the delegate
|
||||
|
||||
const handleDelete = () => delegate.performKeyAction("delete");
|
||||
|
||||
const handleCopy = () => delegate.performKeyAction("copy");
|
||||
|
||||
const handleToggleFullscreen = () =>
|
||||
delegate.performKeyAction("toggle-fullscreen");
|
||||
|
||||
pswp.on("keydown", (e, z) => {
|
||||
const key = e.originalEvent.key ?? "";
|
||||
const cb = (() => {
|
||||
switch (key.toLowerCase()) {
|
||||
case "l":
|
||||
return handleToggleFavorite;
|
||||
return handleToggleFavoriteIfEnabled;
|
||||
case "d":
|
||||
return handleDownload;
|
||||
return handleDownloadIfEnabled;
|
||||
case "i":
|
||||
return handleViewInfo;
|
||||
case "f":
|
||||
return handleToggleFullscreen;
|
||||
}
|
||||
return undefined;
|
||||
})();
|
||||
|
Reference in New Issue
Block a user