aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx')
-rw-r--r--FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx59
1 files changed, 59 insertions, 0 deletions
diff --git a/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx b/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx
new file mode 100644
index 00000000..9bb9f980
--- /dev/null
+++ b/FrontEnd/src/pages/timeline/view/MarkdownPostView.tsx
@@ -0,0 +1,59 @@
+import { useMemo, useState } from "react";
+import { marked } from "marked";
+import classNames from "classnames";
+
+import {
+ HttpTimelinePostInfo,
+ getHttpTimelineClient,
+} from "~src/http/timeline";
+
+import { useAutoUnsubscribePromise } from "~src/components/hooks";
+import Skeleton from "~src/components/Skeleton";
+
+import "./MarkdownPostView.css";
+
+interface MarkdownPostViewProps {
+ post?: HttpTimelinePostInfo;
+ className?: string;
+}
+
+export default function MarkdownPostView({
+ post,
+ className,
+}: MarkdownPostViewProps) {
+ const [markdown, setMarkdown] = useState<string | null>(null);
+
+ useAutoUnsubscribePromise(
+ () => {
+ if (post) {
+ return getHttpTimelineClient().getPostDataAsString(
+ post.timelineOwnerV2,
+ post.timelineNameV2,
+ post.id,
+ );
+ }
+ },
+ setMarkdown,
+ [post],
+ );
+
+ const markdownHtml = useMemo<string | null>(() => {
+ if (markdown == null) return null;
+ return marked.parse(markdown, {
+ async: false,
+ });
+ }, [markdown]);
+
+ return (
+ <div className={classNames("timeline-view-markdown-container", className)}>
+ {markdownHtml == null ? (
+ <Skeleton />
+ ) : (
+ <div
+ className="timeline-view-markdown"
+ dangerouslySetInnerHTML={{ __html: markdownHtml }}
+ />
+ )}
+ </div>
+ );
+}