From 538d6830a0022b49b99695095d85e567b0c86e71 Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 30 Jul 2023 23:47:53 +0800 Subject: ... --- .../src/pages/timeline/TimelinePostContentView.tsx | 187 +++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 FrontEnd/src/pages/timeline/TimelinePostContentView.tsx (limited to 'FrontEnd/src/pages/timeline/TimelinePostContentView.tsx') diff --git a/FrontEnd/src/pages/timeline/TimelinePostContentView.tsx b/FrontEnd/src/pages/timeline/TimelinePostContentView.tsx new file mode 100644 index 00000000..41080e10 --- /dev/null +++ b/FrontEnd/src/pages/timeline/TimelinePostContentView.tsx @@ -0,0 +1,187 @@ +import * as React from "react"; +import classnames from "classnames"; +import { marked } from "marked"; + +import { UiLogicError } from "@/common"; + +import { HttpNetworkError } from "@/http/common"; +import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline"; + +import { useUser } from "@/services/user"; + +import Skeleton from "@/views/common/Skeleton"; +import LoadFailReload from "@/views/common/LoadFailReload"; + +const TextView: React.FC = (props) => { + const { post, className, style } = props; + + const [text, setText] = React.useState(null); + const [error, setError] = React.useState<"offline" | "error" | null>(null); + + const [reloadKey, setReloadKey] = React.useState(0); + + React.useEffect(() => { + let subscribe = true; + + setText(null); + setError(null); + + void getHttpTimelineClient() + .getPostDataAsString(post.timelineOwnerV2, post.timelineNameV2, post.id) + .then( + (data) => { + if (subscribe) setText(data); + }, + (error) => { + if (subscribe) { + if (error instanceof HttpNetworkError) { + setError("offline"); + } else { + setError("error"); + } + } + } + ); + + return () => { + subscribe = false; + }; + }, [post.timelineOwnerV2, post.timelineNameV2, post.id, reloadKey]); + + if (error != null) { + return ( + setReloadKey(reloadKey + 1)} + /> + ); + } else if (text == null) { + return ; + } else { + return ( +
+ {text} +
+ ); + } +}; + +const ImageView: React.FC = (props) => { + const { post, className, style } = props; + + useUser(); + + return ( + + ); +}; + +const MarkdownView: React.FC = (props) => { + const { post, className, style } = props; + + 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.timelineOwnerV2, post.timelineNameV2, post.id) + .then( + (data) => { + if (subscribe) setMarkdown(data); + }, + (error) => { + if (subscribe) { + if (error instanceof HttpNetworkError) { + setError("offline"); + } else { + setError("error"); + } + } + } + ); + + return () => { + subscribe = false; + }; + }, [post.timelineOwnerV2, post.timelineNameV2, post.id, reloadKey]); + + const markdownHtml = React.useMemo(() => { + if (markdown == null) return null; + return marked.parse(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 { + post: HttpTimelinePostInfo; + className?: string; + style?: React.CSSProperties; +} + +const viewMap: Record> = { + "text/plain": TextView, + "text/markdown": MarkdownView, + "image/png": ImageView, + "image/jpeg": ImageView, + "image/gif": ImageView, + "image/webp": ImageView, +}; + +const TimelinePostContentView: React.FC = ( + props +) => { + const { post, className, style } = props; + + const type = post.dataList[0].kind; + + if (type in viewMap) { + const View = viewMap[type]; + return ; + } else { + // TODO: i18n + console.error("Unknown post type", post); + return
Error, unknown post type!
; + } +}; + +export default TimelinePostContentView; -- cgit v1.2.3