From 928ba0ce419bacba113951095278a5138ead34cf Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 10 Apr 2022 16:04:03 +0800 Subject: ... --- FrontEnd/src/views/timeline/MarkdownPostEdit.tsx | 209 +++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 FrontEnd/src/views/timeline/MarkdownPostEdit.tsx (limited to 'FrontEnd/src/views/timeline/MarkdownPostEdit.tsx') diff --git a/FrontEnd/src/views/timeline/MarkdownPostEdit.tsx b/FrontEnd/src/views/timeline/MarkdownPostEdit.tsx new file mode 100644 index 00000000..35a2bbf5 --- /dev/null +++ b/FrontEnd/src/views/timeline/MarkdownPostEdit.tsx @@ -0,0 +1,209 @@ +import React from "react"; +import classnames from "classnames"; +import { useTranslation } from "react-i18next"; + +import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline"; + +import TimelinePostBuilder from "@/services/TimelinePostBuilder"; + +import FlatButton from "../common/button/FlatButton"; +import TabPages from "../common/tab/TabPages"; +import ConfirmDialog from "../common/dailog/ConfirmDialog"; +import Spinner from "../common/Spinner"; + +import "./MarkdownPostEdit.css"; + +export interface MarkdownPostEditProps { + owner: string; + timeline: string; + onPosted: (post: HttpTimelinePostInfo) => void; + onPostError: () => void; + onClose: () => void; + className?: string; + style?: React.CSSProperties; +} + +const MarkdownPostEdit: React.FC = ({ + owner: ownerUsername, + timeline: timelineName, + onPosted, + onClose, + onPostError, + className, + style, +}) => { + const { t } = useTranslation(); + + const [canLeave, setCanLeave] = React.useState(true); + + const [process, setProcess] = React.useState(false); + + const [showLeaveConfirmDialog, setShowLeaveConfirmDialog] = + React.useState(false); + + const [text, _setText] = React.useState(""); + const [images, _setImages] = React.useState<{ file: File; url: string }[]>( + [] + ); + const [previewHtml, _setPreviewHtml] = React.useState(""); + + const _builder = React.useRef(null); + + const getBuilder = (): TimelinePostBuilder => { + if (_builder.current == null) { + const builder = new TimelinePostBuilder(() => { + setCanLeave(builder.isEmpty); + _setText(builder.text); + _setImages(builder.images); + _setPreviewHtml(builder.renderHtml()); + }); + _builder.current = builder; + } + return _builder.current; + }; + + const canSend = text.length > 0; + + React.useEffect(() => { + return () => { + getBuilder().dispose(); + }; + }, []); + + React.useEffect(() => { + window.onbeforeunload = (): unknown => { + if (!canLeave) { + return t("timeline.confirmLeave"); + } + }; + + return () => { + window.onbeforeunload = null; + }; + }, [canLeave, t]); + + const send = async (): Promise => { + setProcess(true); + try { + const dataList = await getBuilder().build(); + const post = await getHttpTimelineClient().postPost( + ownerUsername, + timelineName, + { + dataList, + } + ); + onPosted(post); + onClose(); + } catch (e) { + setProcess(false); + onPostError(); + } + }; + + return ( + <> + + ) : ( +
+ { + if (canLeave) { + onClose(); + } else { + setShowLeaveConfirmDialog(true); + } + }} + /> + {canSend && ( + void send()} /> + )} +
+ ) + } + pages={[ + { + name: "text", + text: "edit", + page: ( +