From 486663e6b4b2aa4addc4c84d24e1ce5252941858 Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 7 Mar 2021 16:15:47 +0800 Subject: feat: Add markdown content view. --- .../timeline-common/TimelinePostContentView.tsx | 82 +++++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) (limited to 'FrontEnd/src/app/views/timeline-common/TimelinePostContentView.tsx') diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePostContentView.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePostContentView.tsx index 2f5d3989..d836d1db 100644 --- a/FrontEnd/src/app/views/timeline-common/TimelinePostContentView.tsx +++ b/FrontEnd/src/app/views/timeline-common/TimelinePostContentView.tsx @@ -1,5 +1,8 @@ import React from "react"; import clsx from "clsx"; +import { Remarkable } from "remarkable"; + +import { UiLogicError } from "@/common"; import { HttpNetworkError } from "@/http/common"; import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline"; @@ -81,9 +84,82 @@ const ImageView: React.FC = (props) => { ); }; -const MarkdownView: React.FC = (_props) => { - // TODO: Implement this. - return
Unsupported now!
; +const MarkdownView: React.FC = (props) => { + const { post, className, style } = props; + + const _remarkable = React.useRef(); + + const getRemarkable = (): Remarkable => { + if (_remarkable.current) { + return _remarkable.current; + } else { + _remarkable.current = new Remarkable(); + return _remarkable.current; + } + }; + + const [markdown, setMarkdown] = React.useState(null); + const [error, setError] = React.useState<"offline" | "error" | null>(null); + + const [reloadKey, setReloadKey] = React.useState(0); + + React.useEffect(() => { + let subscribe = true; + + setMarkdown(null); + setError(null); + + void getHttpTimelineClient() + .getPostDataAsString(post.timelineName, post.id) + .then( + (data) => { + if (subscribe) setMarkdown(data); + }, + (error) => { + if (subscribe) { + if (error instanceof HttpNetworkError) { + setError("offline"); + } else { + setError("error"); + } + } + } + ); + + return () => { + subscribe = false; + }; + }, [post.timelineName, post.id, reloadKey]); + + const markdownHtml = React.useMemo(() => { + if (markdown == null) return null; + return getRemarkable().render(markdown); + }, [markdown]); + + if (error != null) { + return ( + setReloadKey(reloadKey + 1)} + /> + ); + } else if (markdown == null) { + return ; + } else { + if (markdownHtml == null) { + throw new UiLogicError("Markdown is not null but markdown html is."); + } + return ( +
+ ); + } }; export interface TimelinePostContentViewProps { -- cgit v1.2.3