refactor: image preview
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import ImagePreviewModal, { PreviewImageData } from "../../common/component/ImagePreviewModal";
|
||||
type Props = {
|
||||
context?: "chat" | "markdown",
|
||||
container: HTMLElement | null
|
||||
}
|
||||
|
||||
const ImagePreview = ({ container, context = "chat" }: Props) => {
|
||||
const [previewImage, setPreviewImage] = useState<PreviewImageData | null>(null);
|
||||
const closePreviewModal = () => {
|
||||
setPreviewImage(null);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!container) return;
|
||||
const chatHandler = (evt: MouseEvent) => {
|
||||
const target = evt.target as HTMLImageElement;
|
||||
if (!target) return;
|
||||
if (target.nodeName == "IMG" && target.classList.contains("preview")) {
|
||||
const thumbnail = target.src;
|
||||
const originUrl = target.dataset.origin || target.src;
|
||||
const downloadLink = target.dataset.download || target.src;
|
||||
const meta = JSON.parse(target.dataset.meta || "{}");
|
||||
setPreviewImage({ thumbnail, originUrl, downloadLink, ...meta });
|
||||
}
|
||||
};
|
||||
const markdownHandler = (evt: MouseEvent) => {
|
||||
evt.stopPropagation();
|
||||
const target = evt.target as HTMLImageElement;
|
||||
if (!target) return;
|
||||
// 图片
|
||||
if (target.nodeName == "IMG") {
|
||||
const urlObj = new URL(target.src);
|
||||
const originUrl = `${urlObj.origin}${urlObj.pathname}?file_path=${urlObj.searchParams.get(
|
||||
"file_path"
|
||||
)}`;
|
||||
const data = { originUrl };
|
||||
setPreviewImage(data);
|
||||
}
|
||||
};
|
||||
|
||||
const handler = context == 'chat' ? chatHandler : markdownHandler;
|
||||
// 点击查看大图
|
||||
container.addEventListener("click", handler, true);
|
||||
return () => {
|
||||
container.removeEventListener("click", handler, true);
|
||||
};
|
||||
}, [container, context]);
|
||||
return previewImage ? <ImagePreviewModal download={context == "chat"} data={previewImage} closeModal={closePreviewModal} /> : null;
|
||||
|
||||
};
|
||||
|
||||
export default ImagePreview;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useState, useRef, FC } from "react";
|
||||
import { useRef, FC } from "react";
|
||||
import "prismjs/themes/prism.css";
|
||||
import '@toast-ui/editor/dist/theme/toastui-editor-dark.css';
|
||||
import "@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight.css";
|
||||
@@ -6,8 +6,8 @@ import "@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin
|
||||
import codeSyntaxHighlight from "@toast-ui/editor-plugin-code-syntax-highlight/dist/toastui-editor-plugin-code-syntax-highlight-all.js";
|
||||
import { Viewer } from "@toast-ui/react-editor";
|
||||
|
||||
import ImagePreviewModal, { PreviewImageData } from "./ImagePreviewModal";
|
||||
import { isDarkMode } from "../utils";
|
||||
import ImagePreview from "./ImagePreview";
|
||||
|
||||
|
||||
interface IProps {
|
||||
@@ -15,42 +15,9 @@ interface IProps {
|
||||
}
|
||||
const MarkdownRender: FC<IProps> = ({ content }) => {
|
||||
const mdContainer = useRef<HTMLDivElement | null>(null);
|
||||
const [previewImage, setPreviewImage] = useState<PreviewImageData | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const container = mdContainer?.current;
|
||||
if (!container) return;
|
||||
// 点击查看大图
|
||||
// todo: 事件代理
|
||||
container.addEventListener(
|
||||
"click",
|
||||
(evt) => {
|
||||
evt.stopPropagation();
|
||||
const target = evt.target as HTMLImageElement;
|
||||
if (!target) return;
|
||||
// 图片
|
||||
if (target.nodeName == "IMG") {
|
||||
const urlObj = new URL(target.src);
|
||||
const originUrl = `${urlObj.origin}${urlObj.pathname}?file_path=${urlObj.searchParams.get(
|
||||
"file_path"
|
||||
)}`;
|
||||
const data = { originUrl };
|
||||
setPreviewImage(data);
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
}, []);
|
||||
|
||||
const closePreviewModal = () => {
|
||||
setPreviewImage(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{previewImage && (
|
||||
<ImagePreviewModal download={false} data={previewImage} closeModal={closePreviewModal} />
|
||||
)}
|
||||
<ImagePreview container={mdContainer.current} context="markdown" />
|
||||
<div ref={mdContainer} id="MARKDOWN_CONTAINER">
|
||||
<Viewer initialValue={content} plugins={[codeSyntaxHighlight]} theme={isDarkMode() ? "dark" : "light"}></Viewer>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user