mirror of
https://github.com/usememos/memos.git
synced 2024-11-11 07:24:18 +03:00
feat: image preview enhancement (#385)
* feat: dialog content enhancement * update * feat: image carousel * update Co-authored-by: boojack <stevenlgtm@gmail.com>
This commit is contained in:
parent
9d8c9609c3
commit
4246232fbe
@ -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: Props) => {
|
||||
const { className, imgUrl } = props;
|
||||
const { className, imgUrls, index } = props;
|
||||
|
||||
const handleImageClick = () => {
|
||||
showPreviewImageDialog(imgUrl);
|
||||
showPreviewImageCarouselDialog(imgUrls, index);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={"image-container " + className} onClick={handleImageClick}>
|
||||
<img src={imgUrl} decoding="async" loading="lazy" />
|
||||
<img src={imgUrls[index]} decoding="async" loading="lazy" />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -16,12 +16,16 @@ const MemoResources: React.FC<Props> = (props: Props) => {
|
||||
window.open(resourceUrl);
|
||||
};
|
||||
|
||||
const imgUrls = imageList.map((resource) => {
|
||||
return `/o/r/${resource.id}/${resource.filename}`;
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="resource-wrapper">
|
||||
{imageList.length > 0 && (
|
||||
<div className="images-wrapper">
|
||||
{imageList.map((resource) => (
|
||||
<Image className="memo-img" key={resource.id} imgUrl={`/o/r/${resource.id}/${resource.filename}`} />
|
||||
{imageList.map((resource, index) => (
|
||||
<Image className="memo-img" key={resource.id} imgUrls={imgUrls} index={index} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
76
web/src/components/PreviewImageCarouselDialog.tsx
Normal file
76
web/src/components/PreviewImageCarouselDialog.tsx
Normal file
@ -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<Props> = ({ 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 (
|
||||
<>
|
||||
<div className="btns-container">
|
||||
<button className="btn" onClick={handleCloseBtnClick}>
|
||||
<Icon.X className="icon-img" />
|
||||
</button>
|
||||
<button className="btn" onClick={handleDownloadBtnClick}>
|
||||
<Icon.Download className="icon-img" />
|
||||
</button>
|
||||
<button className="btn" onClick={handlePrevBtnClick}>
|
||||
<Icon.ArrowLeft className="icon-img" />
|
||||
</button>
|
||||
<button className="btn" onClick={handleNextBtnClick}>
|
||||
<Icon.ArrowRight className="icon-img" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="img-container" onClick={handleImgContainerClick}>
|
||||
<img onClick={(e) => e.stopPropagation()} src={imgUrls[index]} />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default function showPreviewImageCarouselDialog(imgUrls: string[], index: number): void {
|
||||
generateDialog(
|
||||
{
|
||||
className: "preview-image-carousel-dialog",
|
||||
},
|
||||
PreviewImageDialog,
|
||||
{ imgUrls, index }
|
||||
);
|
||||
}
|
34
web/src/less/preview-image-carousel-dialog.less
Normal file
34
web/src/less/preview-image-carousel-dialog.less
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user