From d007d90392df0abda415b7afc731a5adf3d58430 Mon Sep 17 00:00:00 2001 From: Innei Date: Thu, 4 Jul 2024 11:44:27 +0800 Subject: [PATCH] fix: preview image Signed-off-by: Innei --- .../src/components/ui/image/swipe-images.tsx | 8 +- .../src/components/ui/modal/stacked/modal.tsx | 388 +++++++++--------- .../components/ui/modal/stacked/overlay.tsx | 38 +- .../src/modules/entry-column/picture-item.tsx | 21 +- 4 files changed, 242 insertions(+), 213 deletions(-) diff --git a/src/renderer/src/components/ui/image/swipe-images.tsx b/src/renderer/src/components/ui/image/swipe-images.tsx index 06b6f19d2..8ce0e98ae 100644 --- a/src/renderer/src/components/ui/image/swipe-images.tsx +++ b/src/renderer/src/components/ui/image/swipe-images.tsx @@ -79,8 +79,9 @@ export function SwipeImages({ height: 600, }} disableContextMenu - onClick={() => { + onClick={(e) => { onPreview?.(images, i) + e.stopPropagation() }} /> @@ -104,7 +105,10 @@ export function SwipeImages({ ) : uniqImages?.length >= 1 ? ( onPreview?.(uniqImages)} + onClick={(e) => { + onPreview?.(uniqImages) + e.stopPropagation() + }} className="size-full rounded-none object-cover sm:transition-transform sm:duration-300 sm:ease-in-out sm:group-hover:scale-105" alt="cover" src={uniqImages[0]} diff --git a/src/renderer/src/components/ui/modal/stacked/modal.tsx b/src/renderer/src/components/ui/modal/stacked/modal.tsx index 32ed0f198..c200eefde 100644 --- a/src/renderer/src/components/ui/modal/stacked/modal.tsx +++ b/src/renderer/src/components/ui/modal/stacked/modal.tsx @@ -8,6 +8,7 @@ import { useSetAtom } from "jotai" import type { PointerEventHandler, SyntheticEvent } from "react" import { createElement, + forwardRef, Fragment, memo, useCallback, @@ -33,220 +34,229 @@ export const ModalInternal: Component<{ isTop: boolean onClose?: (open: boolean) => void -}> = memo(function Modal({ - item, - index, - onClose: onPropsClose, - children, - isTop, -}) { - const setStack = useSetAtom(modalStackAtom) - const close = useEventCallback(() => { - setStack((p) => p.filter((modal) => modal.id !== item.id)) - onPropsClose?.(false) - }) +}> = memo( + forwardRef(function Modal( + { item, index, onClose: onPropsClose, children, isTop }, + ref: any, + ) { + const setStack = useSetAtom(modalStackAtom) + const close = useEventCallback(() => { + setStack((p) => p.filter((modal) => modal.id !== item.id)) + onPropsClose?.(false) + }) - const onClose = useCallback( - (open: boolean): void => { - if (!open) { + const onClose = useCallback( + (open: boolean): void => { + if (!open) { + close() + } + }, + [close], + ) + + const opaque = useUISettingKey("modalOpaque") + + const { + CustomModalComponent, + modalClassName, + content, + title, + clickOutsideToDismiss, + modalContainerClassName, + wrapper: Wrapper = Fragment, + max, + icon, + + draggable = false, + } = item + const zIndexStyle = useMemo( + () => ({ zIndex: MODAL_STACK_Z_INDEX + index + 1 }), + [index], + ) + const dismiss = useCallback( + (e: SyntheticEvent) => { + e.stopPropagation() close() - } - }, - [close], - ) + }, + [close], + ) - const opaque = useUISettingKey("modalOpaque") - - const { - CustomModalComponent, - modalClassName, - content, - title, - clickOutsideToDismiss, - modalContainerClassName, - wrapper: Wrapper = Fragment, - max, - icon, - - draggable = false, - } = item - const zIndexStyle = useMemo(() => ({ zIndex: MODAL_STACK_Z_INDEX + index + 1 }), [index]) - const dismiss = useCallback( - (e: SyntheticEvent) => { - e.stopPropagation() - close() - }, - [close], - ) - - const animateController = useAnimationControls() - useEffect(() => { - requestAnimationFrame(() => { - animateController.start(modalMontionConfig.animate) - }) - }, [animateController]) - const noticeModal = useCallback(() => { - animateController - .start({ - scale: 1.05, - transition: { - duration: 0.06, - }, + const animateController = useAnimationControls() + useEffect(() => { + requestAnimationFrame(() => { + animateController.start(modalMontionConfig.animate) }) - .then(() => { - animateController.start({ - scale: 1, + }, [animateController]) + const noticeModal = useCallback(() => { + animateController + .start({ + scale: 1.05, + transition: { + duration: 0.06, + }, }) + .then(() => { + animateController.start({ + scale: 1, + }) + }) + }, [animateController]) + + const dragController = useDragControls() + const handleDrag: PointerEventHandler = useCallback( + (e) => { + if (draggable) { + dragController.start(e) + } + }, + [dragController, draggable], + ) + + useEffect(() => { + if (isTop) return + animateController.start({ + scale: 0.96, + y: 10, }) - }, [animateController]) - - const dragController = useDragControls() - const handleDrag: PointerEventHandler = useCallback( - (e) => { - if (draggable) { - dragController.start(e) + return () => { + try { + animateController.stop() + animateController.start({ + scale: 1, + y: 0, + }) + } catch { + /* empty */ + } } - }, - [dragController, draggable], - ) + }, [isTop]) - useEffect(() => { - if (isTop) return - animateController.start({ - scale: 0.96, - y: 10, - }) - return () => { - try { - animateController.stop() - animateController.start({ - scale: 1, - y: 0, - }) - } catch { - /* empty */ - } + const modalContentRef = useRef(null) + const ModalProps: ModalContentPropsInternal = useMemo( + () => ({ + dismiss: close, + }), + [close], + ) + + const ModalContextProps = useMemo( + () => ({ + ...ModalProps, + ref: modalContentRef, + }), + [ModalProps], + ) + const finalChildren = ( + + {children ?? createElement(content, ModalProps)} + + ) + + const edgeElementRef = useRef(null) + + if (CustomModalComponent) { + return ( + + + + + {title} + + +
+
+ {finalChildren} +
+
+
+
+
+
+ ) } - }, [isTop]) - const modalContentRef = useRef(null) - const ModalProps: ModalContentPropsInternal = useMemo( - () => ({ - dismiss: close, - }), - [close], - ) - - const ModalContextProps = useMemo( - () => ({ - ...ModalProps, - ref: modalContentRef, - }), - [ModalProps], - ) - const finalChildren = ( - - {children ?? createElement(content, ModalProps)} - - ) - - const edgeElementRef = useRef(null) - - if (CustomModalComponent) { return ( - {title}
-
- {finalChildren} -
+
+ + {icon && {icon}} + + {title} + + + + +
+ + +
+ {finalChildren} +
+
) - } - - return ( - - - - -
- -
- - {icon && {icon}} - - {title} - - - - -
- - -
- {finalChildren} -
- -
-
-
-
-
-
- ) -}) + }), +) diff --git a/src/renderer/src/components/ui/modal/stacked/overlay.tsx b/src/renderer/src/components/ui/modal/stacked/overlay.tsx index 9b30778df..02f4ae7a1 100644 --- a/src/renderer/src/components/ui/modal/stacked/overlay.tsx +++ b/src/renderer/src/components/ui/modal/stacked/overlay.tsx @@ -1,23 +1,25 @@ import { m } from "@renderer/components/common/Motion" +import type { ForwardedRef } from "react" +import { forwardRef } from "react" import { RootPortal } from "../../portal" -export const ModalOverlay = ({ - onClick, - zIndex, -}: { - onClick?: () => void - zIndex?: number -}) => ( - - - +export const ModalOverlay = forwardRef( + ( + { onClick, zIndex }: { onClick?: () => void, zIndex?: number }, + ref: ForwardedRef, + ) => ( + + + + ), ) diff --git a/src/renderer/src/modules/entry-column/picture-item.tsx b/src/renderer/src/modules/entry-column/picture-item.tsx index 278cb19f3..eaa35335d 100644 --- a/src/renderer/src/modules/entry-column/picture-item.tsx +++ b/src/renderer/src/modules/entry-column/picture-item.tsx @@ -8,19 +8,32 @@ import { useEntry } from "@renderer/store/entry/hooks" import { usePreviewImages } from "../../components/ui/image/hooks" import type { UniversalItemProps } from "./types" -export function PictureItem({ entryId, entryPreview, translation }: UniversalItemProps) { +export function PictureItem({ + entryId, + entryPreview, + translation, +}: UniversalItemProps) { const entry = useEntry(entryId) || entryPreview - const isActive = useRouteParamsSelector(({ entryId }) => entryId === entry?.entries.id) + const isActive = useRouteParamsSelector( + ({ entryId }) => entryId === entry?.entries.id, + ) const previewImage = usePreviewImages() if (!entry) return return ( - +
{