diff options
Diffstat (limited to 'FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx')
-rw-r--r-- | FrontEnd/src/app/views/timeline-common/TimelinePostEdit.tsx | 129 |
1 files changed, 68 insertions, 61 deletions
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"> |