mirror of
https://github.com/ente-io/ente.git
synced 2025-08-13 17:57:31 +00:00
pseudo focus
This commit is contained in:
@@ -17,10 +17,7 @@ import { isDesktop } from "@/base/app";
|
||||
import { SpacedRow } from "@/base/components/containers";
|
||||
import { DialogCloseIconButton } from "@/base/components/mui/DialogCloseIconButton";
|
||||
import { useIsSmallWidth } from "@/base/components/utils/hooks";
|
||||
import {
|
||||
useModalVisibility,
|
||||
type ModalVisibilityProps,
|
||||
} from "@/base/components/utils/modal";
|
||||
import { type ModalVisibilityProps } from "@/base/components/utils/modal";
|
||||
import { useBaseContext } from "@/base/context";
|
||||
import { lowercaseExtension } from "@/base/file-name";
|
||||
import { pt } from "@/base/i18n";
|
||||
@@ -319,14 +316,11 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
const [moreMenuAnchorEl, setMoreMenuAnchorEl] =
|
||||
useState<HTMLElement | null>(null);
|
||||
const [openImageEditor, setOpenImageEditor] = useState(false);
|
||||
const [openConfirmDelete, setOpenConfirmDelete] = useState(false);
|
||||
const [openShortcuts, setOpenShortcuts] = useState(false);
|
||||
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
|
||||
const { show: showConfirmDelete, props: confirmDeleteVisibilityProps } =
|
||||
useModalVisibility();
|
||||
|
||||
const { show: showShortcuts, props: shortcutsVisibilityProps } =
|
||||
useModalVisibility();
|
||||
|
||||
// Callbacks to be invoked (only once) the next time we get an update to the
|
||||
// `files` or `favoriteFileIDs` props.
|
||||
//
|
||||
@@ -359,10 +353,12 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
return false;
|
||||
});
|
||||
setOpenFileInfo(false);
|
||||
setOpenImageEditor(false);
|
||||
// No need to `resetMoreMenuButtonOnMenuClose` since we're closing
|
||||
// anyway and it'll be removed from the DOM.
|
||||
setMoreMenuAnchorEl(null);
|
||||
setOpenImageEditor(false);
|
||||
setOpenConfirmDelete(false);
|
||||
setOpenShortcuts(false);
|
||||
onClose();
|
||||
}, [onTriggerSyncWithRemote, onClose]);
|
||||
|
||||
@@ -424,10 +420,15 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
return onDelete
|
||||
? () => {
|
||||
handleMoreMenuCloseIfNeeded();
|
||||
showConfirmDelete();
|
||||
setOpenConfirmDelete(true);
|
||||
}
|
||||
: undefined;
|
||||
}, [onDelete, showConfirmDelete, handleMoreMenuCloseIfNeeded]);
|
||||
}, [onDelete, handleMoreMenuCloseIfNeeded]);
|
||||
|
||||
const handleConfirmDeleteClose = useCallback(
|
||||
() => setOpenConfirmDelete(false),
|
||||
[],
|
||||
);
|
||||
|
||||
// Not memoized since it uses the frequently changing `activeAnnotatedFile`.
|
||||
const handleDelete = async () => {
|
||||
@@ -626,8 +627,27 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
|
||||
const handleShortcuts = useCallback(() => {
|
||||
handleMoreMenuCloseIfNeeded();
|
||||
showShortcuts();
|
||||
}, [handleMoreMenuCloseIfNeeded, showShortcuts]);
|
||||
setOpenShortcuts(true);
|
||||
}, [handleMoreMenuCloseIfNeeded]);
|
||||
|
||||
const handleShortcutsClose = useCallback(() => setOpenShortcuts(false), []);
|
||||
|
||||
const shouldIgnoreKeyboardEvent = useCallback(() => {
|
||||
// Don't handle keydowns if any of the modals are open.
|
||||
return (
|
||||
openFileInfo ||
|
||||
moreMenuAnchorEl ||
|
||||
openImageEditor ||
|
||||
openConfirmDelete ||
|
||||
openShortcuts
|
||||
);
|
||||
}, [
|
||||
openFileInfo,
|
||||
moreMenuAnchorEl,
|
||||
openImageEditor,
|
||||
openConfirmDelete,
|
||||
openShortcuts,
|
||||
]);
|
||||
|
||||
const performKeyAction = useCallback(
|
||||
(action): FileViewerPhotoSwipeDelegate["performKeyAction"] => {
|
||||
@@ -657,6 +677,7 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
getFiles,
|
||||
isFavorite,
|
||||
toggleFavorite,
|
||||
shouldIgnoreKeyboardEvent,
|
||||
performKeyAction,
|
||||
};
|
||||
}
|
||||
@@ -667,8 +688,15 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
delegate.getFiles = getFiles;
|
||||
delegate.isFavorite = isFavorite;
|
||||
delegate.toggleFavorite = toggleFavorite;
|
||||
delegate.shouldIgnoreKeyboardEvent = shouldIgnoreKeyboardEvent;
|
||||
delegate.performKeyAction = performKeyAction;
|
||||
}, [getFiles, isFavorite, toggleFavorite, performKeyAction]);
|
||||
}, [
|
||||
getFiles,
|
||||
isFavorite,
|
||||
toggleFavorite,
|
||||
shouldIgnoreKeyboardEvent,
|
||||
performKeyAction,
|
||||
]);
|
||||
|
||||
// Notify the listeners, if any, for updates to files or favorites.
|
||||
useEffect(() => {
|
||||
@@ -822,7 +850,8 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
</MoreMenu>
|
||||
{/* TODO(PS): Fix imports */}
|
||||
<ConfirmDeleteFileDialog
|
||||
{...confirmDeleteVisibilityProps}
|
||||
open={openConfirmDelete}
|
||||
onClose={handleConfirmDeleteClose}
|
||||
onConfirm={handleDelete}
|
||||
/>
|
||||
<ImageEditorOverlay
|
||||
@@ -831,7 +860,7 @@ const FileViewer: React.FC<FileViewerProps> = ({
|
||||
file={activeAnnotatedFile?.file}
|
||||
onSaveEditedCopy={handleSaveEditedCopy}
|
||||
/>
|
||||
<Shortcuts {...shortcutsVisibilityProps} />
|
||||
<Shortcuts open={openShortcuts} onClose={handleShortcutsClose} />
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
@@ -73,6 +73,14 @@ export interface FileViewerPhotoSwipeDelegate {
|
||||
* > remain in the disabled state (until the file viewer is closed).
|
||||
*/
|
||||
toggleFavorite: (annotatedFile: FileViewerAnnotatedFile) => Promise<void>;
|
||||
/**
|
||||
* Called when there is a keydown event, and our PhotoSwipe instance wants
|
||||
* to know if it should ignore it or handle it.
|
||||
*
|
||||
* The delegate should return true when, e.g., the file info dialog is
|
||||
* being displayed.
|
||||
*/
|
||||
shouldIgnoreKeyboardEvent: () => boolean;
|
||||
/**
|
||||
* Called when the user triggers a potential action using a keyboard
|
||||
* shortcut.
|
||||
@@ -734,22 +742,18 @@ export class FileViewerPhotoSwipe {
|
||||
const handleToggleFullscreen = () =>
|
||||
delegate.performKeyAction("toggle-fullscreen");
|
||||
|
||||
pswp.on("keydown", (_e) => {
|
||||
const e: KeyboardEvent = _e.originalEvent;
|
||||
pswp.on("keydown", (pswpEvent) => {
|
||||
// Ignore keyboard events when we do not have "focus".
|
||||
if (delegate.shouldIgnoreKeyboardEvent()) {
|
||||
pswpEvent.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
const e: KeyboardEvent = pswpEvent.originalEvent;
|
||||
|
||||
// Even though we ignore shift, Caps lock might still be on.
|
||||
const key = e.key.toLowerCase();
|
||||
|
||||
console.log(
|
||||
e,
|
||||
key,
|
||||
e.shiftKey,
|
||||
e.altKey,
|
||||
e.metaKey,
|
||||
e.ctrlKey,
|
||||
e.code,
|
||||
);
|
||||
|
||||
// Keep the keybindings such that they don't use modifiers, because
|
||||
// these are more likely to interfere with browser shortcuts.
|
||||
//
|
||||
|
Reference in New Issue
Block a user