diff --git a/web/src/components/Image.tsx b/web/src/components/Image.tsx index 16df3e48..85881ef5 100644 --- a/web/src/components/Image.tsx +++ b/web/src/components/Image.tsx @@ -1,21 +1,22 @@ -import showPreviewImageDialog from "./PreviewImageDialog"; +import showPreviewImageCarouselDialog from "./PreviewImageCarouselDialog"; import "../less/image.less"; interface Props { - imgUrl: string; + imgUrls: string[]; + index: number; className?: string; } const Image: React.FC = (props: Props) => { - const { className, imgUrl } = props; + const { className, imgUrls, index } = props; const handleImageClick = () => { - showPreviewImageDialog(imgUrl); + showPreviewImageCarouselDialog(imgUrls, index); }; return (
- +
); }; diff --git a/web/src/components/MemoResources.tsx b/web/src/components/MemoResources.tsx index 160b8dd3..e8aee8dc 100644 --- a/web/src/components/MemoResources.tsx +++ b/web/src/components/MemoResources.tsx @@ -16,12 +16,16 @@ const MemoResources: React.FC = (props: Props) => { window.open(resourceUrl); }; + const imgUrls = imageList.map((resource) => { + return `/o/r/${resource.id}/${resource.filename}`; + }); + return (
{imageList.length > 0 && (
- {imageList.map((resource) => ( - + {imageList.map((resource, index) => ( + ))}
)} diff --git a/web/src/components/PreviewImageCarouselDialog.tsx b/web/src/components/PreviewImageCarouselDialog.tsx new file mode 100644 index 00000000..faaba130 --- /dev/null +++ b/web/src/components/PreviewImageCarouselDialog.tsx @@ -0,0 +1,76 @@ +import * as utils from "../helpers/utils"; +import Icon from "./Icon"; +import { generateDialog } from "./Dialog"; +import "../less/preview-image-carousel-dialog.less"; + +interface Props extends DialogProps { + imgUrls: string[]; + index: number; +} + +const PreviewImageDialog: React.FC = ({ destroy, imgUrls, index }: Props) => { + const handleCloseBtnClick = () => { + destroy(); + }; + + const handleDownloadBtnClick = () => { + const a = document.createElement("a"); + a.href = imgUrls[index]; + a.download = `memos-${utils.getDateTimeString(Date.now())}.png`; + a.click(); + }; + + const handleImgContainerClick = () => { + destroy(); + }; + + const handlePrevBtnClick = () => { + destroy(); + if (index > 0) { + showPreviewImageCarouselDialog(imgUrls, index - 1); + } else { + showPreviewImageCarouselDialog(imgUrls, imgUrls.length - 1); + } + }; + + const handleNextBtnClick = () => { + destroy(); + if (index < imgUrls.length - 1) { + showPreviewImageCarouselDialog(imgUrls, index + 1); + } else { + showPreviewImageCarouselDialog(imgUrls, 0); + } + }; + + return ( + <> +
+ + + + +
+
+ e.stopPropagation()} src={imgUrls[index]} /> +
+ + ); +}; + +export default function showPreviewImageCarouselDialog(imgUrls: string[], index: number): void { + generateDialog( + { + className: "preview-image-carousel-dialog", + }, + PreviewImageDialog, + { imgUrls, index } + ); +} diff --git a/web/src/less/preview-image-carousel-dialog.less b/web/src/less/preview-image-carousel-dialog.less new file mode 100644 index 00000000..e3a54cd2 --- /dev/null +++ b/web/src/less/preview-image-carousel-dialog.less @@ -0,0 +1,34 @@ +@import "./mixin.less"; + +.preview-image-carousel-dialog { + @apply p-0; + z-index: 101; + background-color: rgba(0, 0, 0, 0.6); + + > .dialog-container { + @apply flex flex-col justify-center items-center relative w-full h-full p-0; + background-color: unset; + + > .btns-container { + @apply fixed top-8 right-8 flex flex-col justify-start items-center; + + > .btn { + @apply mb-3 last:mb-0 w-8 h-8 p-1 cursor-pointer rounded opacity-90 bg-gray-300 z-10 shadow-md hover:opacity-70; + + > .icon-img { + @apply w-6 h-auto; + } + } + } + + > .img-container { + @apply w-full h-full p-4 flex flex-col justify-center items-center; + background-color: unset; + .hide-scroll-bar(); + + > img { + @apply h-auto w-auto max-w-full max-h-full shadow; + } + } + } +}