From c8bd19aacf9059f740df4f6fa9890127c20c1f6d Mon Sep 17 00:00:00 2001
From: crupest <crupest@outlook.com>
Date: Sat, 13 Feb 2021 21:23:30 +0800
Subject: ...

---
 .../app/views/timeline-common/TimelinePostEdit.tsx | 129 +++++++++++----------
 1 file changed, 68 insertions(+), 61 deletions(-)

(limited to 'FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx')

diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx
index 488b627c..7c49e5bb 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx
@@ -5,8 +5,14 @@ import { Button, Spinner, Row, Col, Form } from "react-bootstrap";
 
 import { UiLogicError } from "@/common";
 
+import {
+  getHttpTimelineClient,
+  HttpTimelineInfo,
+  HttpTimelinePostPostRequestData,
+} from "@/http/timeline";
+
 import { pushAlert } from "@/services/alert";
-import { HttpTimelineInfo } from "@/http/timeline";
+import { base64 } from "@/http/common";
 
 interface TimelinePostEditImageProps {
   onSelect: (blob: Blob | null) => void;
@@ -77,19 +83,21 @@ const TimelinePostEditImage: React.FC<TimelinePostEditImageProps> = (props) => {
 export interface TimelinePostEditProps {
   className?: string;
   timeline: HttpTimelineInfo;
+  onPosted: () => void;
   onHeightChange?: (height: number) => void;
 }
 
 const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
-  const { t } = useTranslation();
+  const { timeline, onHeightChange, className, onPosted } = props;
 
-  const { timeline } = props;
+  const { t } = useTranslation();
 
   const [state, setState] = React.useState<"input" | "process">("input");
   const [kind, setKind] = React.useState<"text" | "image">("text");
   const [text, setText] = React.useState<string>("");
+  const [imageBlob, setImageBlob] = React.useState<Blob | null>(null);
 
-  const draftLocalStorageKey = `timeline.${props.timelineUniqueId}.postDraft`;
+  const draftLocalStorageKey = `timeline.${timeline.name}.postDraft`;
 
   React.useEffect(() => {
     setText(window.localStorage.getItem(draftLocalStorageKey) ?? "");
@@ -101,77 +109,76 @@ const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
   const containerRef = React.useRef<HTMLDivElement>(null!);
 
   const notifyHeightChange = (): void => {
-    if (props.onHeightChange) {
-      props.onHeightChange(containerRef.current.clientHeight);
+    if (onHeightChange) {
+      onHeightChange(containerRef.current.clientHeight);
     }
   };
 
   React.useEffect(() => {
-    if (props.onHeightChange) {
-      props.onHeightChange(containerRef.current.clientHeight);
+    if (onHeightChange) {
+      onHeightChange(containerRef.current.clientHeight);
     }
     return () => {
-      if (props.onHeightChange) {
-        props.onHeightChange(0);
+      if (onHeightChange) {
+        onHeightChange(0);
       }
     };
   });
 
   const toggleKind = React.useCallback(() => {
-    // TODO: Implement this.
-    // setKind((oldKind) => (oldKind === "text" ? "image" : "text"));
-    // setImageBlob(null);
+    setKind((oldKind) => (oldKind === "text" ? "image" : "text"));
+    setImageBlob(null);
   }, []);
 
-  const onSend = React.useCallback(() => {
+  const onSend = async (): Promise<void> => {
     setState("process");
 
-    // TODO: Implement this.
-
-    // const req: TimelineCreatePostRequest = (() => {
-    //   switch (kind) {
-    //     case "text":
-    //       return {
-    //         content: {
-    //           type: "text",
-    //           text: text,
-    //         },
-    //       } as TimelineCreatePostRequest;
-    //     case "image":
-    //       if (imageBlob == null) {
-    //         throw new UiLogicError(
-    //           "Content type is image but image blob is null."
-    //         );
-    //       }
-    //       return {
-    //         content: {
-    //           type: "image",
-    //           data: imageBlob,
-    //         },
-    //       } as TimelineCreatePostRequest;
-    //     default:
-    //       throw new UiLogicError("Unknown content type.");
-    //   }
-    // })();
-
-    // onPost(req).then(
-    //   (_) => {
-    //     if (kind === "text") {
-    //       setText("");
-    //       window.localStorage.removeItem(draftLocalStorageKey);
-    //     }
-    //     setState("input");
-    //     setKind("text");
-    //   },
-    //   (_) => {
-    //     pushAlert({
-    //       type: "danger",
-    //       message: t("timeline.sendPostFailed"),
-    //     });
-    //     setState("input");
-    //   }
-    // );
-  }, []);
+    let requestData: HttpTimelinePostPostRequestData;
+    switch (kind) {
+      case "text":
+        requestData = {
+          contentType: "text/plain",
+          data: await base64(new Blob([text])),
+        };
+        break;
+      case "image":
+        if (imageBlob == null) {
+          throw new UiLogicError(
+            "Content type is image but image blob is null."
+          );
+        }
+        requestData = {
+          contentType: imageBlob.type,
+          data: await base64(imageBlob),
+        };
+        break;
+      default:
+        throw new UiLogicError("Unknown content type.");
+    }
+
+    getHttpTimelineClient()
+      .postPost(timeline.name, {
+        dataList: [requestData],
+      })
+      .then(
+        (_) => {
+          if (kind === "text") {
+            setText("");
+            window.localStorage.removeItem(draftLocalStorageKey);
+          }
+          setState("input");
+          setKind("text");
+          onPosted();
+        },
+        (_) => {
+          pushAlert({
+            type: "danger",
+            message: t("timeline.sendPostFailed"),
+          });
+          setState("input");
+        }
+      );
+  };
 
   const onImageSelect = React.useCallback((blob: Blob | null) => {
     setImageBlob(blob);
@@ -180,7 +187,7 @@ const TimelinePostEdit: React.FC<TimelinePostEditProps> = (props) => {
   return (
     <div
       ref={containerRef}
-      className={clsx("container-fluid bg-light", props.className)}
+      className={clsx("container-fluid bg-light", className)}
     >
       <Row>
         <Col className="px-1 py-1">
-- 
cgit v1.2.3

