Refactor escape handling
This commit is contained in:
parent
637e5cd2d3
commit
cae1da9f6a
@ -9,6 +9,7 @@ import AnimateItems from './AnimateItems';
|
||||
import { PATH_ROOT } from '@/site/paths';
|
||||
import usePrefersReducedMotion from '@/utility/usePrefersReducedMotion';
|
||||
import useMetaThemeColor from '@/site/useMetaThemeColor';
|
||||
import useEscapeHandler from '@/photo/useEscapeHandler';
|
||||
|
||||
export default function Modal({
|
||||
onClosePath,
|
||||
@ -55,6 +56,8 @@ export default function Modal({
|
||||
},
|
||||
});
|
||||
|
||||
useEscapeHandler(onClose, true);
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
className={clsx(
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import useKeydownHandler from '@/utility/useKeydownHandler';
|
||||
import { RefObject, useCallback, useEffect, useRef } from 'react';
|
||||
import Viewer from 'viewerjs';
|
||||
|
||||
const EVENT_SHOWN = 'shown';
|
||||
const EVENT_HIDDEN = 'hidden';
|
||||
const EVENT_KEYDOWN = 'keydown';
|
||||
|
||||
export default function useImageZoomControls(
|
||||
imageRef: RefObject<HTMLDivElement | null>,
|
||||
@ -13,7 +13,7 @@ export default function useImageZoomControls(
|
||||
) {
|
||||
const viewerRef = useRef<Viewer | null>(null);
|
||||
|
||||
const { isCommandKOpen, setShouldRespondToKeyboardCommands } = useAppState();
|
||||
const { setShouldRespondToKeyboardCommands } = useAppState();
|
||||
|
||||
useEffect(() => {
|
||||
if (imageRef.current && isEnabled) {
|
||||
@ -67,21 +67,12 @@ export default function useImageZoomControls(
|
||||
}, [imageRef, onHide]);
|
||||
|
||||
// On 'F' keydown, toggle fullscreen
|
||||
const handleKeyDown = useCallback((e: KeyboardEvent) => {
|
||||
if (
|
||||
shouldExpandOnFKeydown &&
|
||||
!isCommandKOpen &&
|
||||
e.key.toUpperCase() === 'F'
|
||||
) {
|
||||
const handleKeyDown = useCallback(() => {
|
||||
if (shouldExpandOnFKeydown) {
|
||||
viewerRef.current?.show();
|
||||
}
|
||||
}, [shouldExpandOnFKeydown, isCommandKOpen]);
|
||||
useEffect(() => {
|
||||
document.addEventListener(EVENT_KEYDOWN, handleKeyDown);
|
||||
return () => {
|
||||
document.removeEventListener(EVENT_KEYDOWN, handleKeyDown);
|
||||
};
|
||||
}, [handleKeyDown]);
|
||||
}, [shouldExpandOnFKeydown]);
|
||||
useKeydownHandler(handleKeyDown, ['F']);
|
||||
|
||||
return {
|
||||
open,
|
||||
|
||||
@ -1,32 +1,22 @@
|
||||
'use client';
|
||||
|
||||
import { getEscapePath } from '@/site/paths';
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import { useRouter, usePathname } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const LISTENER_KEYUP = 'keyup';
|
||||
import { useCallback } from 'react';
|
||||
import useEscapeHandler from './useEscapeHandler';
|
||||
|
||||
export default function PhotoEscapeHandler() {
|
||||
const router = useRouter();
|
||||
|
||||
const pathname = usePathname();
|
||||
|
||||
const { shouldRespondToKeyboardCommands } = useAppState();
|
||||
|
||||
const escapePath = getEscapePath(pathname);
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldRespondToKeyboardCommands) {
|
||||
const onKeyUp = (e: KeyboardEvent) => {
|
||||
if (e.key?.toUpperCase() === 'ESCAPE' && escapePath) {
|
||||
router.push(escapePath, { scroll: false });
|
||||
};
|
||||
};
|
||||
window.addEventListener(LISTENER_KEYUP, onKeyUp);
|
||||
return () => window.removeEventListener(LISTENER_KEYUP, onKeyUp);
|
||||
}
|
||||
}, [shouldRespondToKeyboardCommands, router, escapePath]);
|
||||
const escapeHandler = useCallback(() => {
|
||||
if (escapePath) { router.push(escapePath, { scroll: false }); }
|
||||
}, [escapePath, router]);
|
||||
|
||||
useEscapeHandler(escapeHandler);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
12
src/photo/useEscapeHandler.ts
Normal file
12
src/photo/useEscapeHandler.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import useKeydownHandler from '@/utility/useKeydownHandler';
|
||||
|
||||
export default function useEscapeHandler(
|
||||
onEscape?: () => void,
|
||||
ignoreShouldRespondToKeyboardCommands?: boolean,
|
||||
) {
|
||||
useKeydownHandler(
|
||||
onEscape,
|
||||
['ESCAPE'],
|
||||
ignoreShouldRespondToKeyboardCommands,
|
||||
);
|
||||
}
|
||||
@ -4,7 +4,7 @@ import Modal from '@/components/Modal';
|
||||
import { TbPhotoShare } from 'react-icons/tb';
|
||||
import { clsx } from 'clsx/lite';
|
||||
import { BiCopy } from 'react-icons/bi';
|
||||
import { JSX, ReactNode } from 'react';
|
||||
import { JSX, ReactNode, useEffect } from 'react';
|
||||
import { shortenUrl } from '@/utility/url';
|
||||
import { toastSuccess } from '@/toast';
|
||||
import { PiXLogo } from 'react-icons/pi';
|
||||
@ -24,7 +24,15 @@ export default function ShareModal({
|
||||
socialText: string
|
||||
children: ReactNode
|
||||
}) {
|
||||
const { setShareModalProps } = useAppState();
|
||||
const {
|
||||
setShareModalProps,
|
||||
setShouldRespondToKeyboardCommands,
|
||||
} = useAppState();
|
||||
|
||||
useEffect(() => {
|
||||
setShouldRespondToKeyboardCommands?.(false);
|
||||
return () => setShouldRespondToKeyboardCommands?.(true);
|
||||
}, [setShouldRespondToKeyboardCommands]);
|
||||
|
||||
const renderIcon = (
|
||||
icon: JSX.Element,
|
||||
|
||||
32
src/utility/useKeydownHandler.ts
Normal file
32
src/utility/useKeydownHandler.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { useAppState } from '@/state/AppState';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
const LISTENER_KEYDOWN = 'keydown';
|
||||
|
||||
export default function useKeydownHandler(
|
||||
onKeydown?: (e: KeyboardEvent) => void,
|
||||
keys: string[] = [],
|
||||
ignoreShouldRespondToKeyboardCommands?: boolean,
|
||||
) {
|
||||
const { shouldRespondToKeyboardCommands } = useAppState();
|
||||
|
||||
const onKeyUp = useCallback((e: KeyboardEvent) => {
|
||||
if (keys.some(key => key.toUpperCase() === e.key?.toUpperCase())) {
|
||||
onKeydown?.(e);
|
||||
}
|
||||
}, [onKeydown, keys]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
shouldRespondToKeyboardCommands ||
|
||||
ignoreShouldRespondToKeyboardCommands
|
||||
) {
|
||||
window.addEventListener(LISTENER_KEYDOWN, onKeyUp);
|
||||
return () => window.removeEventListener(LISTENER_KEYDOWN, onKeyUp);
|
||||
}
|
||||
}, [
|
||||
shouldRespondToKeyboardCommands,
|
||||
ignoreShouldRespondToKeyboardCommands,
|
||||
onKeyUp,
|
||||
]);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user